Cocoa Port: Fix a whole slew of synchronization issues in the entire client display system, hopefully improving stability.

- Of special note, Metal display views aren't allowed to run on macOS High Sierra because of an assert bug in [id<MTLDevice> newBufferWithBytesNoCopy:length:options:deallocator:] in this particular version of macOS. Note that Metal display views will continue to work with macOS El Capitan and macOS Sierra.
This commit is contained in:
rogerman 2017-11-10 01:31:50 -08:00
parent 57f5fa0e6e
commit 89a74e5c3e
16 changed files with 1204 additions and 747 deletions

View File

@ -72,8 +72,8 @@ void ClientDisplayPresenter::__InstanceInit(const ClientDisplayPresenterProperti
_displaySourceSelect[NDSDisplayID_Main] = ClientDisplaySource_DeterminedByNDS;
_displaySourceSelect[NDSDisplayID_Touch] = ClientDisplaySource_DeterminedByNDS;
_isSelectedDisplayEnabled[NDSDisplayID_Main] = true;
_isSelectedDisplayEnabled[NDSDisplayID_Touch] = true;
_isSelectedDisplayEnabled[NDSDisplayID_Main] = false;
_isSelectedDisplayEnabled[NDSDisplayID_Touch] = false;
_selectedSourceForDisplay[NDSDisplayID_Main] = NDSDisplayID_Main;
_selectedSourceForDisplay[NDSDisplayID_Touch] = NDSDisplayID_Touch;
@ -820,7 +820,7 @@ void ClientDisplayPresenter::LoadDisplays()
case ClientDisplaySource_EngineMain:
{
if ( (this->_emuDisplayInfo.engineID[NDSDisplayID_Main] == GPUEngineID_Main) && (mainDisplaySrc == ClientDisplaySource_EngineMain) )
if (this->_emuDisplayInfo.engineID[NDSDisplayID_Main] == GPUEngineID_Main)
{
this->_selectedSourceForDisplay[NDSDisplayID_Main] = NDSDisplayID_Main;
this->_isSelectedDisplayEnabled[NDSDisplayID_Main] = this->_emuDisplayInfo.isDisplayEnabled[NDSDisplayID_Main];
@ -835,7 +835,7 @@ void ClientDisplayPresenter::LoadDisplays()
case ClientDisplaySource_EngineSub:
{
if ( (this->_emuDisplayInfo.engineID[NDSDisplayID_Main] == GPUEngineID_Sub) && (mainDisplaySrc == ClientDisplaySource_EngineSub) )
if (this->_emuDisplayInfo.engineID[NDSDisplayID_Main] == GPUEngineID_Sub)
{
this->_selectedSourceForDisplay[NDSDisplayID_Main] = NDSDisplayID_Main;
this->_isSelectedDisplayEnabled[NDSDisplayID_Main] = this->_emuDisplayInfo.isDisplayEnabled[NDSDisplayID_Main];
@ -863,7 +863,7 @@ void ClientDisplayPresenter::LoadDisplays()
case ClientDisplaySource_EngineMain:
{
if ( (this->_emuDisplayInfo.engineID[NDSDisplayID_Touch] == GPUEngineID_Main) && (touchDisplaySrc == ClientDisplaySource_EngineMain) )
if (this->_emuDisplayInfo.engineID[NDSDisplayID_Touch] == GPUEngineID_Main)
{
this->_selectedSourceForDisplay[NDSDisplayID_Touch] = NDSDisplayID_Touch;
this->_isSelectedDisplayEnabled[NDSDisplayID_Touch] = this->_emuDisplayInfo.isDisplayEnabled[NDSDisplayID_Touch];
@ -878,7 +878,7 @@ void ClientDisplayPresenter::LoadDisplays()
case ClientDisplaySource_EngineSub:
{
if ( (this->_emuDisplayInfo.engineID[NDSDisplayID_Touch] == GPUEngineID_Sub) && (touchDisplaySrc == ClientDisplaySource_EngineSub) )
if (this->_emuDisplayInfo.engineID[NDSDisplayID_Touch] == GPUEngineID_Sub)
{
this->_selectedSourceForDisplay[NDSDisplayID_Touch] = NDSDisplayID_Touch;
this->_isSelectedDisplayEnabled[NDSDisplayID_Touch] = this->_emuDisplayInfo.isDisplayEnabled[NDSDisplayID_Touch];
@ -960,11 +960,6 @@ void ClientDisplayPresenter::CopyFrameToBuffer(uint32_t *dstBuffer)
// Do nothing. This is implementation dependent.
}
void ClientDisplayPresenter::FinishFrameAtIndex(const uint8_t bufferIndex)
{
// Do nothing. This is implementation dependent.
}
const NDSDisplayInfo& ClientDisplayPresenter::GetEmuDisplayInfo() const
{
return this->_emuDisplayInfo;

View File

@ -301,7 +301,6 @@ public:
virtual void LoadDisplays();
virtual void ProcessDisplays();
virtual void UpdateLayout();
virtual void FinishFrameAtIndex(const uint8_t bufferIndex);
virtual void CopyFrameToBuffer(uint32_t *dstBuffer);

View File

@ -4551,6 +4551,9 @@ OGLClientFetchObject::OGLClientFetchObject()
pthread_rwlock_init(&_srcCloneRWLock[NDSDisplayID_Main][1], NULL);
pthread_rwlock_init(&_srcCloneRWLock[NDSDisplayID_Touch][1], NULL);
pthread_rwlock_init(&_texFetchRWLock[NDSDisplayID_Main], NULL);
pthread_rwlock_init(&_texFetchRWLock[NDSDisplayID_Touch], NULL);
_srcNativeCloneMaster = (uint32_t *)malloc_alignedPage(GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2 * 2 * sizeof(uint32_t));
_srcNativeClone[NDSDisplayID_Main][0] = _srcNativeCloneMaster + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 0);
_srcNativeClone[NDSDisplayID_Touch][0] = _srcNativeCloneMaster + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 1);
@ -4593,6 +4596,9 @@ OGLClientFetchObject::~OGLClientFetchObject()
pthread_rwlock_destroy(&this->_srcCloneRWLock[NDSDisplayID_Touch][0]);
pthread_rwlock_destroy(&this->_srcCloneRWLock[NDSDisplayID_Main][1]);
pthread_rwlock_destroy(&this->_srcCloneRWLock[NDSDisplayID_Touch][1]);
pthread_rwlock_destroy(&this->_texFetchRWLock[NDSDisplayID_Main]);
pthread_rwlock_destroy(&this->_texFetchRWLock[NDSDisplayID_Touch]);
}
OGLContextInfo* OGLClientFetchObject::GetContextInfo() const
@ -4675,6 +4681,21 @@ void OGLClientFetchObject::FetchNativeDisplayToSrcClone(const NDSDisplayID displ
}
}
void OGLClientFetchObject::FetchTextureWriteLock(const NDSDisplayID displayID)
{
pthread_rwlock_wrlock(&this->_texFetchRWLock[displayID]);
}
void OGLClientFetchObject::FetchTextureReadLock(const NDSDisplayID displayID)
{
pthread_rwlock_rdlock(&this->_texFetchRWLock[displayID]);
}
void OGLClientFetchObject::FetchTextureUnlock(const NDSDisplayID displayID)
{
pthread_rwlock_unlock(&this->_texFetchRWLock[displayID]);
}
void OGLClientFetchObject::Init()
{
glGenTextures(4, &this->_texDisplayFetchNative[0][0]);
@ -4738,6 +4759,9 @@ void OGLClientFetchObject::Init()
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
this->_texFetch[NDSDisplayID_Main] = this->_texDisplayFetchNative[NDSDisplayID_Main][0];
this->_texFetch[NDSDisplayID_Touch] = this->_texDisplayFetchNative[NDSDisplayID_Touch][0];
if (this->_contextInfo->IsShaderSupported())
{
SetupHQnxLUTs_OGL(GL_TEXTURE0 + 1, this->_texLQ2xLUT, this->_texHQ2xLUT, this->_texHQ3xLUT, this->_texHQ4xLUT);
@ -4751,15 +4775,28 @@ void OGLClientFetchObject::Init()
void OGLClientFetchObject::SetFetchBuffers(const NDSDisplayInfo &currentDisplayInfo)
{
const size_t nativeSize = GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * currentDisplayInfo.pixelBytes;
const size_t customSize = currentDisplayInfo.customWidth * currentDisplayInfo.customHeight * currentDisplayInfo.pixelBytes;
this->_fetchDisplayInfo[0] = currentDisplayInfo;
this->_fetchDisplayInfo[1] = currentDisplayInfo;
this->_fetchDisplayInfo[0].nativeBuffer[NDSDisplayID_Main] = (u8 *)currentDisplayInfo.masterFramebufferHead;
this->_fetchDisplayInfo[0].nativeBuffer[NDSDisplayID_Touch] = (u8 *)currentDisplayInfo.masterFramebufferHead + (nativeSize * 1);
this->_fetchDisplayInfo[0].customBuffer[NDSDisplayID_Main] = (u8 *)currentDisplayInfo.masterFramebufferHead + (nativeSize * 2);
this->_fetchDisplayInfo[0].customBuffer[NDSDisplayID_Touch] = (u8 *)currentDisplayInfo.masterFramebufferHead + (nativeSize * 2) + customSize;
this->_fetchDisplayInfo[1].nativeBuffer[NDSDisplayID_Main] = (u8 *)this->_fetchDisplayInfo[0].nativeBuffer[NDSDisplayID_Main] + currentDisplayInfo.framebufferSize;
this->_fetchDisplayInfo[1].nativeBuffer[NDSDisplayID_Touch] = (u8 *)this->_fetchDisplayInfo[0].nativeBuffer[NDSDisplayID_Touch] + currentDisplayInfo.framebufferSize;
this->_fetchDisplayInfo[1].customBuffer[NDSDisplayID_Main] = (u8 *)this->_fetchDisplayInfo[0].customBuffer[NDSDisplayID_Main] + currentDisplayInfo.framebufferSize;
this->_fetchDisplayInfo[1].customBuffer[NDSDisplayID_Touch] = (u8 *)this->_fetchDisplayInfo[0].customBuffer[NDSDisplayID_Touch] + currentDisplayInfo.framebufferSize;
#ifdef MSB_FIRST
this->_fetchColorFormatOGL = (currentDisplayInfo.pixelBytes == 2) ? GL_UNSIGNED_SHORT_1_5_5_5_REV : GL_UNSIGNED_INT_8_8_8_8;
#else
this->_fetchColorFormatOGL = (currentDisplayInfo.pixelBytes == 2) ? GL_UNSIGNED_SHORT_1_5_5_5_REV : GL_UNSIGNED_INT_8_8_8_8_REV;
#endif
const size_t nativeSize = GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * currentDisplayInfo.pixelBytes;
const size_t customSize = currentDisplayInfo.customWidth * currentDisplayInfo.customHeight * currentDisplayInfo.pixelBytes;
glFinish();
glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_ARB, currentDisplayInfo.framebufferSize * 2, currentDisplayInfo.masterFramebufferHead);
@ -4767,35 +4804,35 @@ void OGLClientFetchObject::SetFetchBuffers(const NDSDisplayInfo &currentDisplayI
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texDisplayFetchNative[NDSDisplayID_Main][0]);
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, this->_fetchColorFormatOGL, (u8 *)currentDisplayInfo.masterFramebufferHead);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, 0, GL_RGBA, this->_fetchColorFormatOGL, this->_fetchDisplayInfo[0].nativeBuffer[NDSDisplayID_Main]);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texDisplayFetchNative[NDSDisplayID_Main][1]);
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, this->_fetchColorFormatOGL, (u8 *)currentDisplayInfo.masterFramebufferHead + currentDisplayInfo.framebufferSize);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, 0, GL_RGBA, this->_fetchColorFormatOGL, this->_fetchDisplayInfo[1].nativeBuffer[NDSDisplayID_Main]);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texDisplayFetchNative[NDSDisplayID_Touch][0]);
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, this->_fetchColorFormatOGL, (u8 *)currentDisplayInfo.masterFramebufferHead + (nativeSize * 1));
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, 0, GL_RGBA, this->_fetchColorFormatOGL, this->_fetchDisplayInfo[0].nativeBuffer[NDSDisplayID_Touch]);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texDisplayFetchNative[NDSDisplayID_Touch][1]);
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, this->_fetchColorFormatOGL, (u8 *)currentDisplayInfo.masterFramebufferHead + (nativeSize * 1) + currentDisplayInfo.framebufferSize);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, 0, GL_RGBA, this->_fetchColorFormatOGL, this->_fetchDisplayInfo[1].nativeBuffer[NDSDisplayID_Touch]);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texDisplayFetchCustom[NDSDisplayID_Main][0]);
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, (u8 *)currentDisplayInfo.masterFramebufferHead + (nativeSize * 2));
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, currentDisplayInfo.customWidth, currentDisplayInfo.customHeight, 0, GL_RGBA, this->_fetchColorFormatOGL, this->_fetchDisplayInfo[0].customBuffer[NDSDisplayID_Main]);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texDisplayFetchCustom[NDSDisplayID_Main][1]);
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, (u8 *)currentDisplayInfo.masterFramebufferHead + (nativeSize * 2) + currentDisplayInfo.framebufferSize);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, currentDisplayInfo.customWidth, currentDisplayInfo.customHeight, 0, GL_RGBA, this->_fetchColorFormatOGL, this->_fetchDisplayInfo[1].customBuffer[NDSDisplayID_Main]);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texDisplayFetchCustom[NDSDisplayID_Touch][0]);
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, (u8 *)currentDisplayInfo.masterFramebufferHead + (nativeSize * 2) + customSize);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, currentDisplayInfo.customWidth, currentDisplayInfo.customHeight, 0, GL_RGBA, this->_fetchColorFormatOGL, this->_fetchDisplayInfo[0].customBuffer[NDSDisplayID_Touch]);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texDisplayFetchCustom[NDSDisplayID_Touch][1]);
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, (u8 *)currentDisplayInfo.masterFramebufferHead + (nativeSize * 2) + customSize + currentDisplayInfo.framebufferSize);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, currentDisplayInfo.customWidth, currentDisplayInfo.customHeight, 0, GL_RGBA, this->_fetchColorFormatOGL, this->_fetchDisplayInfo[1].customBuffer[NDSDisplayID_Touch]);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
@ -4818,6 +4855,45 @@ void OGLClientFetchObject::SetFetchBuffers(const NDSDisplayInfo &currentDisplayI
pthread_rwlock_unlock(&this->_srcCloneRWLock[NDSDisplayID_Touch][1]);
}
void OGLClientFetchObject::FetchFromBufferIndex(const u8 index)
{
GPUClientFetchObject::FetchFromBufferIndex(index);
glFlush();
GLuint texFetchMain = 0;
GLuint texFetchTouch = 0;
const NDSDisplayInfo &currentDisplayInfo = this->GetFetchDisplayInfoForBufferIndex(index);
const bool isMainEnabled = currentDisplayInfo.isDisplayEnabled[NDSDisplayID_Main];
const bool isTouchEnabled = currentDisplayInfo.isDisplayEnabled[NDSDisplayID_Touch];
if (isMainEnabled)
{
if (!currentDisplayInfo.didPerformCustomRender[NDSDisplayID_Main])
{
texFetchMain = this->_texDisplayFetchNative[NDSDisplayID_Main][index];
}
else
{
texFetchMain = this->_texDisplayFetchCustom[NDSDisplayID_Main][index];
}
}
if (isTouchEnabled)
{
if (!currentDisplayInfo.didPerformCustomRender[NDSDisplayID_Touch])
{
texFetchTouch = this->_texDisplayFetchNative[NDSDisplayID_Touch][index];
}
else
{
texFetchTouch = this->_texDisplayFetchCustom[NDSDisplayID_Touch][index];
}
}
this->SetFetchTexture(NDSDisplayID_Main, texFetchMain);
this->SetFetchTexture(NDSDisplayID_Touch, texFetchTouch);
}
void OGLClientFetchObject::_FetchNativeDisplayByID(const NDSDisplayID displayID, const u8 bufferIndex)
{
pthread_rwlock_wrlock(&this->_srcCloneRWLock[displayID][bufferIndex]);
@ -4840,6 +4916,16 @@ void OGLClientFetchObject::_FetchCustomDisplayByID(const NDSDisplayID displayID,
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;
}
#pragma mark -
OGLVideoOutput::OGLVideoOutput()
@ -4854,6 +4940,12 @@ OGLVideoOutput::OGLVideoOutput()
_texCPUFilterDstID[NDSDisplayID_Touch] = 0;
_fboFrameCopyID = 0;
_processedFrameInfo.bufferIndex = 0;
_processedFrameInfo.texID[NDSDisplayID_Main] = 0;
_processedFrameInfo.texID[NDSDisplayID_Touch] = 0;
_processedFrameInfo.isMainDisplayProcessed = false;
_processedFrameInfo.isTouchDisplayProcessed = false;
_layerList = new std::vector<OGLVideoLayer *>;
_layerList->reserve(8);
}
@ -5084,19 +5176,6 @@ void OGLVideoOutput::ProcessDisplays()
}
}
void OGLVideoOutput::FinishFrameAtIndex(const uint8_t bufferIndex)
{
for (size_t i = 0; i < _layerList->size(); i++)
{
OGLVideoLayer *theLayer = (*_layerList)[i];
if (theLayer->IsVisible())
{
theLayer->FinishOGL(bufferIndex);
}
}
}
void OGLVideoOutput::CopyFrameToBuffer(uint32_t *dstBuffer)
{
GLuint texFrameCopyID = 0;
@ -5149,12 +5228,27 @@ void OGLVideoOutput::RenderFrameOGL(bool isRenderingFlipped)
}
}
void OGLVideoOutput::LockDisplayTextures()
const OGLProcessedFrameInfo& OGLVideoOutput::GetProcessedFrameInfo()
{
return this->_processedFrameInfo;
}
void OGLVideoOutput::SetProcessedFrameInfo(const OGLProcessedFrameInfo &processedInfo)
{
this->_processedFrameInfo = processedInfo;
}
void OGLVideoOutput::WriteLockEmuFramebuffer(const uint8_t bufferIndex)
{
// Do nothing. This is implementation dependent.
}
void OGLVideoOutput::UnlockDisplayTextures()
void OGLVideoOutput::ReadLockEmuFramebuffer(const uint8_t bufferIndex)
{
// Do nothing. This is implementation dependent.
}
void OGLVideoOutput::UnlockEmuFramebuffer(const uint8_t bufferIndex)
{
// Do nothing. This is implementation dependent.
}
@ -6568,8 +6662,10 @@ OGLDisplayLayer::OGLDisplayLayer(OGLVideoOutput *oglVO)
_displayTexFilter[0] = GL_NEAREST;
_displayTexFilter[1] = GL_NEAREST;
_texVideoOutputID[0] = 0;
_texVideoOutputID[1] = 0;
pthread_rwlock_init(&_cpuFilterRWLock[NDSDisplayID_Main][0], NULL);
pthread_rwlock_init(&_cpuFilterRWLock[NDSDisplayID_Touch][0], NULL);
pthread_rwlock_init(&_cpuFilterRWLock[NDSDisplayID_Main][1], NULL);
pthread_rwlock_init(&_cpuFilterRWLock[NDSDisplayID_Touch][1], NULL);
// Set up VBOs
glGenBuffersARB(1, &_vboVertexID);
@ -6676,6 +6772,11 @@ OGLDisplayLayer::~OGLDisplayLayer()
delete this->_shaderFilter[0];
delete this->_shaderFilter[1];
}
pthread_rwlock_destroy(&this->_cpuFilterRWLock[NDSDisplayID_Main][0]);
pthread_rwlock_destroy(&this->_cpuFilterRWLock[NDSDisplayID_Touch][0]);
pthread_rwlock_destroy(&this->_cpuFilterRWLock[NDSDisplayID_Main][1]);
pthread_rwlock_destroy(&this->_cpuFilterRWLock[NDSDisplayID_Touch][1]);
}
void OGLDisplayLayer::_UpdateRotationScaleOGL()
@ -7062,110 +7163,237 @@ void OGLDisplayLayer::LoadNativeDisplayByID_OGL(const NDSDisplayID displayID)
OGLClientFetchObject &fetchObjMutable = (OGLClientFetchObject &)this->_output->GetFetchObject();
VideoFilter *vf = this->_output->GetPixelScalerObject(displayID);
fetchObjMutable.CopyFromSrcClone(vf->GetSrcBufferPtr(), displayID, this->_output->GetEmuDisplayInfo().bufferIndex);
}
}
const uint8_t bufferIndex = fetchObjMutable.GetLastFetchIndex();
void OGLDisplayLayer::_ProcessDisplayByID(const NDSDisplayID displayID, GLsizei &inoutWidth, GLsizei &inoutHeight, GLuint &inoutTexID)
{
VideoFilter *vf = this->_output->GetPixelScalerObject(displayID);
const bool willFilterOnGPU = this->_output->WillFilterOnGPU();
const bool useDeposterize = this->_output->GetSourceDeposterize();
// Source
if (useDeposterize)
{
// For all shader-based filters, we need to temporarily disable GL_UNPACK_CLIENT_STORAGE_APPLE.
// Filtered images are supposed to remain on the GPU for immediate use for further GPU processing,
// so using client-backed buffers for filtered images would simply waste memory here.
glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
inoutTexID = this->_filterDeposterize[displayID]->RunFilterOGL(inoutTexID);
glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
if ((this->_output->GetPixelScaler() != VideoFilterTypeID_None) && !willFilterOnGPU) // Hybrid CPU/GPU-based path (may cause a performance hit on pixel download)
{
this->_filterDeposterize[displayID]->DownloadDstBufferOGL(vf->GetSrcBufferPtr(), 0, vf->GetSrcHeight());
}
}
// Pixel scaler
if (this->_output->GetPixelScaler() != VideoFilterTypeID_None)
{
if (willFilterOnGPU)
{
glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
inoutTexID = this->_shaderFilter[displayID]->RunFilterOGL(inoutTexID);
glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
inoutWidth = vf->GetDstWidth();
inoutHeight = vf->GetDstHeight();
}
else
{
uint32_t *texData = vf->RunFilter();
inoutTexID = this->_output->GetTexCPUFilterDstID(displayID);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, inoutTexID);
glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, vf->GetDstWidth(), vf->GetDstHeight(), GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, texData);
inoutWidth = (GLsizei)vf->GetDstWidth();
inoutHeight = (GLsizei)vf->GetDstHeight();
}
pthread_rwlock_wrlock(&this->_cpuFilterRWLock[displayID][bufferIndex]);
fetchObjMutable.CopyFromSrcClone(vf->GetSrcBufferPtr(), displayID, bufferIndex);
pthread_rwlock_unlock(&this->_cpuFilterRWLock[displayID][bufferIndex]);
}
}
void OGLDisplayLayer::ProcessOGL()
{
const OGLClientFetchObject &fetchObj = (const OGLClientFetchObject &)this->_output->GetFetchObject();
OGLClientFetchObject &fetchObj = (OGLClientFetchObject &)this->_output->GetFetchObject();
const uint8_t bufferIndex = fetchObj.GetLastFetchIndex();
const NDSDisplayInfo &emuDisplayInfo = this->_output->GetEmuDisplayInfo();
const ClientDisplayMode mode = this->_output->GetPresenterProperties().mode;
const bool useDeposterize = this->_output->GetSourceDeposterize();
const NDSDisplayID selectedDisplaySource[2] = { this->_output->GetSelectedDisplaySourceForDisplay(NDSDisplayID_Main), this->_output->GetSelectedDisplaySourceForDisplay(NDSDisplayID_Touch) };
const bool didRenderNative[2] = { !emuDisplayInfo.didPerformCustomRender[selectedDisplaySource[NDSDisplayID_Main]], !emuDisplayInfo.didPerformCustomRender[selectedDisplaySource[NDSDisplayID_Touch]] };
GLuint texVideoSourceID[2] = { (didRenderNative[NDSDisplayID_Main]) ? fetchObj.GetTexNative(selectedDisplaySource[NDSDisplayID_Main], emuDisplayInfo.bufferIndex) : fetchObj.GetTexCustom(selectedDisplaySource[NDSDisplayID_Main], emuDisplayInfo.bufferIndex),
(didRenderNative[NDSDisplayID_Touch]) ? fetchObj.GetTexNative(selectedDisplaySource[NDSDisplayID_Touch], emuDisplayInfo.bufferIndex) : fetchObj.GetTexCustom(selectedDisplaySource[NDSDisplayID_Touch], emuDisplayInfo.bufferIndex) };
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);
GLsizei width[2] = { emuDisplayInfo.renderedWidth[selectedDisplaySource[NDSDisplayID_Main]], emuDisplayInfo.renderedWidth[selectedDisplaySource[NDSDisplayID_Touch]] };
GLsizei height[2] = { emuDisplayInfo.renderedHeight[selectedDisplaySource[NDSDisplayID_Main]], emuDisplayInfo.renderedHeight[selectedDisplaySource[NDSDisplayID_Touch]] };
if (emuDisplayInfo.pixelBytes != 0)
VideoFilter *vfMain = this->_output->GetPixelScalerObject(NDSDisplayID_Main);
VideoFilter *vfTouch = this->_output->GetPixelScalerObject(NDSDisplayID_Touch);
bool isDisplayProcessedMain = false;
bool isDisplayProcessedTouch = false;
if ( (emuDisplayInfo.pixelBytes != 0) && (useDeposterize || (this->_output->GetPixelScaler() != VideoFilterTypeID_None)) )
{
// Run the video source filters and the pixel scalers
const bool willFilterOnGPU = this->_output->WillFilterOnGPU();
const bool useDeposterize = this->_output->GetSourceDeposterize();
const bool needProcessDisplay[2] = { (didRenderNative[NDSDisplayID_Main] || !emuDisplayInfo.isCustomSizeRequested) && this->_output->IsSelectedDisplayEnabled(NDSDisplayID_Main) && (mode == ClientDisplayMode_Main || mode == ClientDisplayMode_Dual),
const bool shouldProcessDisplay[2] = { (didRenderNative[NDSDisplayID_Main] || !emuDisplayInfo.isCustomSizeRequested) && this->_output->IsSelectedDisplayEnabled(NDSDisplayID_Main) && (mode == ClientDisplayMode_Main || mode == ClientDisplayMode_Dual),
(didRenderNative[NDSDisplayID_Touch] || !emuDisplayInfo.isCustomSizeRequested) && this->_output->IsSelectedDisplayEnabled(NDSDisplayID_Touch) && (mode == ClientDisplayMode_Touch || mode == ClientDisplayMode_Dual) && (selectedDisplaySource[NDSDisplayID_Main] != selectedDisplaySource[NDSDisplayID_Touch]) };
const bool needsLock = (willFilterOnGPU || useDeposterize) && (needProcessDisplay[NDSDisplayID_Main] || needProcessDisplay[NDSDisplayID_Touch]);
if (needsLock)
bool texFetchMainNeedsLock = (useDeposterize || ((this->_output->GetPixelScaler() != VideoFilterTypeID_None) && willFilterOnGPU)) && shouldProcessDisplay[NDSDisplayID_Main];
bool texFetchTouchNeedsLock = (useDeposterize || ((this->_output->GetPixelScaler() != VideoFilterTypeID_None) && willFilterOnGPU)) && shouldProcessDisplay[NDSDisplayID_Touch];
bool needsFetchBuffersLock = texFetchMainNeedsLock || texFetchTouchNeedsLock;
if (needsFetchBuffersLock)
{
this->_output->LockDisplayTextures();
this->_output->ReadLockEmuFramebuffer(bufferIndex);
}
if (needProcessDisplay[NDSDisplayID_Main])
if (useDeposterize)
{
this->_ProcessDisplayByID(NDSDisplayID_Main, width[NDSDisplayID_Main], height[NDSDisplayID_Main], texVideoSourceID[NDSDisplayID_Main]);
if (shouldProcessDisplay[NDSDisplayID_Main])
{
if (texFetchMainNeedsLock)
{
fetchObj.FetchTextureReadLock(NDSDisplayID_Main);
}
if (needProcessDisplay[NDSDisplayID_Touch])
// For all shader-based filters, we need to temporarily disable GL_UNPACK_CLIENT_STORAGE_APPLE.
// Filtered images are supposed to remain on the GPU for immediate use for further GPU processing,
// so using client-backed buffers for filtered images would simply waste memory here.
glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
texMain = this->_filterDeposterize[NDSDisplayID_Main]->RunFilterOGL(texMain);
glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
if (texFetchMainNeedsLock)
{
this->_ProcessDisplayByID(NDSDisplayID_Touch, width[NDSDisplayID_Touch], height[NDSDisplayID_Touch], texVideoSourceID[NDSDisplayID_Touch]);
fetchObj.FetchTextureUnlock(NDSDisplayID_Main);
}
if (needsLock)
isDisplayProcessedMain = true;
texFetchMainNeedsLock = false;
if (selectedDisplaySource[NDSDisplayID_Main] == selectedDisplaySource[NDSDisplayID_Touch])
{
this->_output->UnlockDisplayTextures();
isDisplayProcessedTouch = true;
texFetchTouchNeedsLock = false;
}
}
if (shouldProcessDisplay[NDSDisplayID_Touch])
{
if (texFetchTouchNeedsLock)
{
fetchObj.FetchTextureReadLock(NDSDisplayID_Touch);
}
glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
texTouch = this->_filterDeposterize[NDSDisplayID_Touch]->RunFilterOGL(texTouch);
glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
if (texFetchTouchNeedsLock)
{
fetchObj.FetchTextureUnlock(NDSDisplayID_Touch);
}
isDisplayProcessedTouch = true;
texFetchTouchNeedsLock = false;
}
if (needsFetchBuffersLock && (!shouldProcessDisplay[NDSDisplayID_Main] || isDisplayProcessedMain) && (!shouldProcessDisplay[NDSDisplayID_Touch] || isDisplayProcessedTouch))
{
glFinish();
needsFetchBuffersLock = false;
this->_output->UnlockEmuFramebuffer(bufferIndex);
}
}
// Run the pixel scalers. First attempt on the GPU.
if ( (this->_output->GetPixelScaler() != VideoFilterTypeID_None) && willFilterOnGPU )
{
if (shouldProcessDisplay[NDSDisplayID_Main])
{
if (texFetchMainNeedsLock)
{
fetchObj.FetchTextureReadLock(NDSDisplayID_Main);
}
glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
texMain = this->_shaderFilter[NDSDisplayID_Main]->RunFilterOGL(texMain);
glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
if (texFetchMainNeedsLock)
{
fetchObj.FetchTextureUnlock(NDSDisplayID_Main);
}
width[NDSDisplayID_Main] = (GLsizei)vfMain->GetDstWidth();
height[NDSDisplayID_Main] = (GLsizei)vfMain->GetDstHeight();
isDisplayProcessedMain = true;
texFetchMainNeedsLock = false;
if (selectedDisplaySource[NDSDisplayID_Main] == selectedDisplaySource[NDSDisplayID_Touch])
{
isDisplayProcessedTouch = true;
texFetchTouchNeedsLock = false;
}
}
if (shouldProcessDisplay[NDSDisplayID_Touch])
{
if (texFetchTouchNeedsLock)
{
fetchObj.FetchTextureReadLock(NDSDisplayID_Touch);
}
glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
texTouch = this->_shaderFilter[NDSDisplayID_Touch]->RunFilterOGL(texTouch);
glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
if (texFetchTouchNeedsLock)
{
fetchObj.FetchTextureUnlock(NDSDisplayID_Touch);
}
width[NDSDisplayID_Touch] = (GLsizei)vfTouch->GetDstWidth();
height[NDSDisplayID_Touch] = (GLsizei)vfTouch->GetDstHeight();
isDisplayProcessedTouch = true;
texFetchTouchNeedsLock = false;
}
if (needsFetchBuffersLock && (!shouldProcessDisplay[NDSDisplayID_Main] || isDisplayProcessedMain) && (!shouldProcessDisplay[NDSDisplayID_Touch] || isDisplayProcessedTouch))
{
glFinish();
needsFetchBuffersLock = false;
this->_output->UnlockEmuFramebuffer(bufferIndex);
}
}
// If the pixel scaler didn't already run on the GPU, then run the pixel scaler on the CPU.
if ( (this->_output->GetPixelScaler() != VideoFilterTypeID_None) && !willFilterOnGPU )
{
if (useDeposterize)
{
// Hybrid CPU/GPU-based path (may cause a performance hit on pixel download)
if (shouldProcessDisplay[NDSDisplayID_Main])
{
this->_filterDeposterize[NDSDisplayID_Main]->DownloadDstBufferOGL(vfMain->GetSrcBufferPtr(), 0, vfMain->GetSrcHeight());
}
if (shouldProcessDisplay[NDSDisplayID_Touch])
{
this->_filterDeposterize[NDSDisplayID_Touch]->DownloadDstBufferOGL(vfTouch->GetSrcBufferPtr(), 0, vfTouch->GetSrcHeight());
}
}
if (shouldProcessDisplay[NDSDisplayID_Main])
{
pthread_rwlock_rdlock(&this->_cpuFilterRWLock[NDSDisplayID_Main][bufferIndex]);
vfMain->RunFilter();
pthread_rwlock_unlock(&this->_cpuFilterRWLock[NDSDisplayID_Main][bufferIndex]);
}
if (shouldProcessDisplay[NDSDisplayID_Touch])
{
pthread_rwlock_rdlock(&this->_cpuFilterRWLock[NDSDisplayID_Touch][bufferIndex]);
vfTouch->RunFilter();
pthread_rwlock_unlock(&this->_cpuFilterRWLock[NDSDisplayID_Touch][bufferIndex]);
}
if (shouldProcessDisplay[NDSDisplayID_Main])
{
texMain = this->_output->GetTexCPUFilterDstID(NDSDisplayID_Main);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texMain);
glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, vfMain->GetDstWidth(), vfMain->GetDstHeight(), GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, vfMain->GetDstBufferPtr());
width[NDSDisplayID_Main] = (GLsizei)vfMain->GetDstWidth();
height[NDSDisplayID_Main] = (GLsizei)vfMain->GetDstHeight();
isDisplayProcessedMain = true;
if (selectedDisplaySource[NDSDisplayID_Main] == selectedDisplaySource[NDSDisplayID_Touch])
{
isDisplayProcessedTouch = true;
}
}
if (shouldProcessDisplay[NDSDisplayID_Touch])
{
texTouch = this->_output->GetTexCPUFilterDstID(NDSDisplayID_Touch);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texTouch);
glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, vfTouch->GetDstWidth(), vfTouch->GetDstHeight(), GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, vfTouch->GetDstBufferPtr());
width[NDSDisplayID_Touch] = (GLsizei)vfTouch->GetDstWidth();
height[NDSDisplayID_Touch] = (GLsizei)vfTouch->GetDstHeight();
isDisplayProcessedTouch = true;
}
}
}
// Set the final output texture IDs
this->_texVideoOutputID[NDSDisplayID_Main] = texVideoSourceID[NDSDisplayID_Main];
if (selectedDisplaySource[NDSDisplayID_Touch] != selectedDisplaySource[NDSDisplayID_Main])
if (selectedDisplaySource[NDSDisplayID_Touch] == selectedDisplaySource[NDSDisplayID_Main])
{
this->_texVideoOutputID[NDSDisplayID_Touch] = texVideoSourceID[NDSDisplayID_Touch];
}
else
{
this->_texVideoOutputID[NDSDisplayID_Touch] = texVideoSourceID[NDSDisplayID_Main];
texTouch = texMain;
width[NDSDisplayID_Touch] = width[NDSDisplayID_Main];
height[NDSDisplayID_Touch] = height[NDSDisplayID_Main];
}
@ -7183,11 +7411,21 @@ void OGLDisplayLayer::ProcessOGL()
// OpenGL shader-based filters can modify the viewport, so it needs to be reset here.
glViewport(0, 0, this->_output->GetViewportWidth(), this->_output->GetViewportHeight());
glFlush();
OGLProcessedFrameInfo newFrameInfo;
newFrameInfo.bufferIndex = bufferIndex;
newFrameInfo.isMainDisplayProcessed = isDisplayProcessedMain;
newFrameInfo.isTouchDisplayProcessed = isDisplayProcessedTouch;
newFrameInfo.texID[NDSDisplayID_Main] = texMain;
newFrameInfo.texID[NDSDisplayID_Touch] = texTouch;
this->_output->SetProcessedFrameInfo(newFrameInfo);
}
void OGLDisplayLayer::RenderOGL(bool isRenderingFlipped)
{
const NDSDisplayInfo &emuDisplayInfo = this->_output->GetEmuDisplayInfo();
const bool isShaderSupported = this->_output->GetContextInfo()->IsShaderSupported();
if (isShaderSupported)
@ -7227,14 +7465,25 @@ void OGLDisplayLayer::RenderOGL(bool isRenderingFlipped)
this->_UpdateRotationScaleOGL();
}
if (emuDisplayInfo.pixelBytes != 0)
{
if (this->_needUpdateVertices)
{
this->_UpdateVerticesOGL();
}
this->_output->LockDisplayTextures();
OGLClientFetchObject &fetchObj = (OGLClientFetchObject &)this->_output->GetFetchObject();
const NDSDisplayInfo &emuDisplayInfo = this->_output->GetEmuDisplayInfo();
const float backlightIntensity[2] = { emuDisplayInfo.backlightIntensity[NDSDisplayID_Main], emuDisplayInfo.backlightIntensity[NDSDisplayID_Touch] };
const OGLProcessedFrameInfo processedInfo = this->_output->GetProcessedFrameInfo();
bool texFetchMainNeedsLock = !processedInfo.isMainDisplayProcessed;
bool texFetchTouchNeedsLock = !processedInfo.isTouchDisplayProcessed;
const bool needsFetchBuffersLock = texFetchMainNeedsLock || texFetchTouchNeedsLock;
if (needsFetchBuffersLock)
{
this->_output->ReadLockEmuFramebuffer(processedInfo.bufferIndex);
}
glBindVertexArrayDESMUME(this->_vaoMainStatesID);
switch (this->_output->GetPresenterProperties().mode)
@ -7245,13 +7494,25 @@ void OGLDisplayLayer::RenderOGL(bool isRenderingFlipped)
{
if (isShaderSupported)
{
glUniform1f(this->_uniformBacklightIntensity, emuDisplayInfo.backlightIntensity[NDSDisplayID_Main]);
glUniform1f(this->_uniformBacklightIntensity, backlightIntensity[NDSDisplayID_Main]);
}
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoOutputID[NDSDisplayID_Main]);
if (texFetchMainNeedsLock)
{
fetchObj.FetchTextureWriteLock(NDSDisplayID_Main);
}
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, processedInfo.texID[NDSDisplayID_Main]);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, this->_displayTexFilter[NDSDisplayID_Main]);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, this->_displayTexFilter[NDSDisplayID_Main]);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
if (texFetchMainNeedsLock)
{
glFlush();
fetchObj.FetchTextureUnlock(NDSDisplayID_Main);
texFetchMainNeedsLock = false;
}
}
break;
}
@ -7262,13 +7523,25 @@ void OGLDisplayLayer::RenderOGL(bool isRenderingFlipped)
{
if (isShaderSupported)
{
glUniform1f(this->_uniformBacklightIntensity, emuDisplayInfo.backlightIntensity[NDSDisplayID_Touch]);
glUniform1f(this->_uniformBacklightIntensity, backlightIntensity[NDSDisplayID_Touch]);
}
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoOutputID[NDSDisplayID_Touch]);
if (texFetchTouchNeedsLock)
{
fetchObj.FetchTextureWriteLock(NDSDisplayID_Touch);
}
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, processedInfo.texID[NDSDisplayID_Touch]);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, this->_displayTexFilter[NDSDisplayID_Touch]);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, this->_displayTexFilter[NDSDisplayID_Touch]);
glDrawArrays(GL_TRIANGLE_STRIP, 4, 4);
if (texFetchTouchNeedsLock)
{
glFlush();
fetchObj.FetchTextureUnlock(NDSDisplayID_Touch);
texFetchTouchNeedsLock = false;
}
}
break;
}
@ -7278,6 +7551,9 @@ void OGLDisplayLayer::RenderOGL(bool isRenderingFlipped)
const NDSDisplayID majorDisplayID = (this->_output->GetPresenterProperties().order == ClientDisplayOrder_MainFirst) ? NDSDisplayID_Main : NDSDisplayID_Touch;
const size_t majorDisplayVtx = (this->_output->GetPresenterProperties().order == ClientDisplayOrder_MainFirst) ? 8 : 12;
bool texFetchMainAlreadyLocked = false;
bool texFetchTouchAlreadyLocked = false;
switch (this->_output->GetPresenterProperties().layout)
{
case ClientDisplayLayout_Hybrid_2_1:
@ -7288,13 +7564,32 @@ void OGLDisplayLayer::RenderOGL(bool isRenderingFlipped)
{
if (isShaderSupported)
{
glUniform1f(this->_uniformBacklightIntensity, emuDisplayInfo.backlightIntensity[majorDisplayID]);
glUniform1f(this->_uniformBacklightIntensity, backlightIntensity[majorDisplayID]);
}
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoOutputID[majorDisplayID]);
const bool texFetchMajorNeedsLock = (majorDisplayID == NDSDisplayID_Main) ? texFetchMainNeedsLock : texFetchTouchNeedsLock;
if (texFetchMajorNeedsLock)
{
fetchObj.FetchTextureWriteLock(majorDisplayID);
}
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, processedInfo.texID[majorDisplayID]);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, this->_displayTexFilter[majorDisplayID]);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, this->_displayTexFilter[majorDisplayID]);
glDrawArrays(GL_TRIANGLE_STRIP, majorDisplayVtx, 4);
if (texFetchMajorNeedsLock)
{
if (majorDisplayID == NDSDisplayID_Main)
{
texFetchMainAlreadyLocked = true;
}
else
{
texFetchTouchAlreadyLocked = true;
}
}
}
break;
}
@ -7307,26 +7602,50 @@ void OGLDisplayLayer::RenderOGL(bool isRenderingFlipped)
{
if (isShaderSupported)
{
glUniform1f(this->_uniformBacklightIntensity, emuDisplayInfo.backlightIntensity[NDSDisplayID_Main]);
glUniform1f(this->_uniformBacklightIntensity, backlightIntensity[NDSDisplayID_Main]);
}
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoOutputID[NDSDisplayID_Main]);
if (texFetchMainNeedsLock && !texFetchMainAlreadyLocked)
{
fetchObj.FetchTextureWriteLock(NDSDisplayID_Main);
}
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, processedInfo.texID[NDSDisplayID_Main]);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, this->_displayTexFilter[NDSDisplayID_Main]);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, this->_displayTexFilter[NDSDisplayID_Main]);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
if (texFetchMainNeedsLock)
{
glFlush();
fetchObj.FetchTextureUnlock(NDSDisplayID_Main);
texFetchMainNeedsLock = false;
}
}
if (this->_output->IsSelectedDisplayEnabled(NDSDisplayID_Touch))
{
if (isShaderSupported)
{
glUniform1f(this->_uniformBacklightIntensity, emuDisplayInfo.backlightIntensity[NDSDisplayID_Touch]);
glUniform1f(this->_uniformBacklightIntensity, backlightIntensity[NDSDisplayID_Touch]);
}
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoOutputID[NDSDisplayID_Touch]);
if (texFetchTouchNeedsLock && !texFetchTouchAlreadyLocked)
{
fetchObj.FetchTextureWriteLock(NDSDisplayID_Touch);
}
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, processedInfo.texID[NDSDisplayID_Touch]);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, this->_displayTexFilter[NDSDisplayID_Touch]);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, this->_displayTexFilter[NDSDisplayID_Touch]);
glDrawArrays(GL_TRIANGLE_STRIP, 4, 4);
if (texFetchTouchNeedsLock)
{
glFlush();
fetchObj.FetchTextureUnlock(NDSDisplayID_Touch);
texFetchTouchNeedsLock = false;
}
}
}
@ -7335,16 +7654,9 @@ void OGLDisplayLayer::RenderOGL(bool isRenderingFlipped)
}
glBindVertexArrayDESMUME(0);
this->_output->UnlockDisplayTextures();
if (needsFetchBuffersLock)
{
this->_output->UnlockEmuFramebuffer(processedInfo.bufferIndex);
}
}
void OGLDisplayLayer::FinishOGL(const u8 bufferIndex)
{
const OGLClientFetchObject &fetchObj = (const OGLClientFetchObject &)this->_output->GetFetchObject();
glFinishObjectAPPLE(GL_TEXTURE_RECTANGLE_ARB, fetchObj.GetTexNative(NDSDisplayID_Main, bufferIndex));
glFinishObjectAPPLE(GL_TEXTURE_RECTANGLE_ARB, fetchObj.GetTexNative(NDSDisplayID_Touch, bufferIndex));
glFinishObjectAPPLE(GL_TEXTURE_RECTANGLE_ARB, fetchObj.GetTexCustom(NDSDisplayID_Main, bufferIndex));
glFinishObjectAPPLE(GL_TEXTURE_RECTANGLE_ARB, fetchObj.GetTexCustom(NDSDisplayID_Touch, bufferIndex));
}

View File

@ -49,6 +49,15 @@ enum ShaderSupportTier
ShaderSupport_FutureTier = 6,
};
struct OGLProcessedFrameInfo
{
uint8_t bufferIndex;
GLuint texID[2];
bool isMainDisplayProcessed;
bool isTouchDisplayProcessed;
};
typedef struct OGLProcessedFrameInfo OGLProcessedFrameInfo;
class OGLContextInfo
{
protected:
@ -273,7 +282,6 @@ public:
virtual void SetVisibility(const bool visibleState);
virtual void RenderOGL(bool isRenderingFlipped) = 0;
virtual void FinishOGL(const u8 bufferIndex) {};
};
class OGLHUDLayer : public OGLVideoLayer
@ -306,8 +314,7 @@ protected:
OGLFilter *_filterDeposterize[2];
OGLFilter *_shaderFilter[2];
GLint _displayTexFilter[2];
GLuint _texVideoOutputID[2];
pthread_rwlock_t _cpuFilterRWLock[2][2];
GLuint _vaoMainStatesID;
GLuint _vboVertexID;
@ -316,8 +323,6 @@ protected:
void _UpdateRotationScaleOGL();
void _UpdateVerticesOGL();
void _ProcessDisplayByID(const NDSDisplayID displayID, GLsizei &inoutWidth, GLsizei &inoutHeight, GLuint &inoutTexID);
public:
OGLDisplayLayer() {};
OGLDisplayLayer(OGLVideoOutput *oglVO);
@ -328,8 +333,8 @@ public:
void LoadNativeDisplayByID_OGL(const NDSDisplayID displayID);
void ProcessOGL();
virtual void RenderOGL(bool isRenderingFlipped);
virtual void FinishOGL(const u8 bufferIndex);
};
class OGLClientFetchObject : public GPUClientFetchObject
@ -345,10 +350,13 @@ protected:
GLuint _texHQ3xLUT;
GLuint _texHQ4xLUT;
GLuint _texFetch[2];
bool _useDirectToCPUFilterPipeline;
uint32_t *_srcNativeCloneMaster;
uint32_t *_srcNativeClone[2][2];
pthread_rwlock_t _srcCloneRWLock[2][2];
pthread_rwlock_t _texFetchRWLock[2];
bool _srcCloneNeedsUpdate[2][2];
virtual void _FetchNativeDisplayByID(const NDSDisplayID displayID, const u8 bufferIndex);
@ -372,9 +380,16 @@ public:
void CopyFromSrcClone(uint32_t *dstBufferPtr, const NDSDisplayID displayID, const u8 bufferIndex);
void FetchNativeDisplayToSrcClone(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 &currentDisplayInfo);
virtual void FetchFromBufferIndex(const u8 index);
virtual GLuint GetFetchTexture(const NDSDisplayID displayID);
virtual void SetFetchTexture(const NDSDisplayID displayID, GLuint texID);
};
class OGLVideoOutput : public ClientDisplay3DPresenter
@ -389,6 +404,8 @@ protected:
GLuint _texCPUFilterDstID[2];
GLuint _fboFrameCopyID;
OGLProcessedFrameInfo _processedFrameInfo;
std::vector<OGLVideoLayer *> *_layerList;
void _UpdateViewport();
@ -428,11 +445,15 @@ public:
// Client view interface
virtual void ProcessDisplays();
virtual void FinishFrameAtIndex(const uint8_t bufferIndex);
virtual void CopyFrameToBuffer(uint32_t *dstBuffer);;
virtual void CopyFrameToBuffer(uint32_t *dstBuffer);
virtual void RenderFrameOGL(bool isRenderingFlipped);
virtual void LockDisplayTextures();
virtual void UnlockDisplayTextures();
virtual const OGLProcessedFrameInfo& GetProcessedFrameInfo();
virtual void SetProcessedFrameInfo(const OGLProcessedFrameInfo &processedInfo);
virtual void WriteLockEmuFramebuffer(const uint8_t bufferIndex);
virtual void ReadLockEmuFramebuffer(const uint8_t bufferIndex);
virtual void UnlockEmuFramebuffer(const uint8_t bufferIndex);
};
extern void (*glBindVertexArrayDESMUME)(GLuint id);

View File

@ -67,7 +67,6 @@ typedef std::map<CGDirectDisplayID, int64_t> DisplayLinkFlushTimeLimitMap;
- (void) incrementViewsUsingDirectToCPUFiltering;
- (void) decrementViewsUsingDirectToCPUFiltering;
- (void) pushVideoDataToAllDisplayViews;
- (void) finishAllDisplayViewsAtIndex:(const u8)bufferIndex;
- (void) flushAllDisplaysOnDisplayLink:(CVDisplayLinkRef)displayLink timeStamp:(const CVTimeStamp *)timeStamp;
- (void) displayLinkStartUsingID:(CGDirectDisplayID)displayID;

View File

@ -166,6 +166,10 @@ public:
#ifdef ENABLE_APPLE_METAL
if (IsOSXVersionSupported(10, 11, 0) && ![[NSUserDefaults standardUserDefaults] boolForKey:@"Debug_DisableMetal"])
{
// macOS v10.13.0 and v10.13.1 are specifically checked for here, because there are
// bugs in these versions of macOS that prevent Metal from working properly.
if (!IsOSXVersion(10, 13, 0) && !IsOSXVersion(10, 13, 1))
{
fetchObject = new MacMetalFetchObject;
@ -179,6 +183,7 @@ public:
GPU->SetWillPostprocessDisplays(false);
}
}
}
#endif
if (fetchObject == NULL)
@ -189,6 +194,8 @@ public:
fetchObject->Init();
gpuEvent->SetFetchObject(fetchObject);
[self clearWithColor:0x8000];
return self;
}
@ -244,15 +251,16 @@ public:
- (void) setGpuDimensions:(NSSize)theDimensions
{
[[self sharedData] finishAllDisplayViewsAtIndex:0];
[[self sharedData] finishAllDisplayViewsAtIndex:1];
gpuEvent->Render3DLock();
gpuEvent->FramebufferLockWrite();
pthread_rwlock_wrlock([[self sharedData] rwlockFramebufferAtIndex:0]);
pthread_rwlock_wrlock([[self sharedData] rwlockFramebufferAtIndex:1]);
GPU->SetCustomFramebufferSize(theDimensions.width, theDimensions.height);
fetchObject->SetFetchBuffers(GPU->GetDisplayInfo());
pthread_rwlock_unlock([[self sharedData] rwlockFramebufferAtIndex:1]);
pthread_rwlock_unlock([[self sharedData] rwlockFramebufferAtIndex:0]);
gpuEvent->FramebufferUnlock();
gpuEvent->Render3DUnlock();
}
@ -294,15 +302,16 @@ public:
}
// Change the color format.
[[self sharedData] finishAllDisplayViewsAtIndex:0];
[[self sharedData] finishAllDisplayViewsAtIndex:1];
gpuEvent->Render3DLock();
gpuEvent->FramebufferLockWrite();
pthread_rwlock_wrlock([[self sharedData] rwlockFramebufferAtIndex:0]);
pthread_rwlock_wrlock([[self sharedData] rwlockFramebufferAtIndex:1]);
GPU->SetColorFormat((NDSColorFormat)colorFormat);
fetchObject->SetFetchBuffers(GPU->GetDisplayInfo());
pthread_rwlock_unlock([[self sharedData] rwlockFramebufferAtIndex:1]);
pthread_rwlock_unlock([[self sharedData] rwlockFramebufferAtIndex:0]);
gpuEvent->FramebufferUnlock();
gpuEvent->Render3DUnlock();
}
@ -842,8 +851,17 @@ public:
- (void) clearWithColor:(const uint16_t)colorBGRA5551
{
gpuEvent->FramebufferLockWrite();
const u8 bufferIndex = GPU->GetDisplayInfo().bufferIndex;
pthread_rwlock_wrlock([[self sharedData] rwlockFramebufferAtIndex:bufferIndex]);
GPU->ClearWithColor(colorBGRA5551);
pthread_rwlock_unlock([[self sharedData] rwlockFramebufferAtIndex:bufferIndex]);
gpuEvent->FramebufferUnlock();
#if !defined(PORT_VERSION_OPENEMU)
[[self sharedData] signalFetchAtIndex:bufferIndex];
#endif
}
- (void) respondToPauseState:(BOOL)isPaused
@ -1022,30 +1040,6 @@ public:
}
}
- (void) finishAllDisplayViewsAtIndex:(const u8)bufferIndex
{
pthread_mutex_t *currentMutex = _mutexOutputList;
if (currentMutex != NULL)
{
pthread_mutex_lock(currentMutex);
}
for (CocoaDSOutput *cdsOutput in _cdsOutputList)
{
if ([cdsOutput isKindOfClass:[CocoaDSDisplayVideo class]])
{
ClientDisplay3DView *cdv = [(CocoaDSDisplayVideo *)cdsOutput clientDisplay3DView];
cdv->Get3DPresenter()->FinishFrameAtIndex(bufferIndex);
}
}
if (currentMutex != NULL)
{
pthread_mutex_unlock(currentMutex);
}
}
- (void) flushAllDisplaysOnDisplayLink:(CVDisplayLinkRef)displayLink timeStamp:(const CVTimeStamp *)timeStamp
{
pthread_mutex_t *currentMutex = _mutexOutputList;
@ -1190,10 +1184,10 @@ public:
- (void) runFetchLoop
{
do
{
pthread_mutex_lock(&_mutexFetchExecute);
do
{
while (!_isFetchSignalled)
{
pthread_cond_wait(&_condSignalFetch, &_mutexFetchExecute);
@ -1202,8 +1196,6 @@ public:
GPUFetchObject->FetchFromBufferIndex(_fetchIndex);
[self pushVideoDataToAllDisplayViews];
pthread_mutex_unlock(&_mutexFetchExecute);
} while(true);
}

View File

@ -1137,10 +1137,6 @@
- (void) handleReloadReprocessRedraw
{
GPUClientFetchObject &fetchObjMutable = (GPUClientFetchObject &)_cdv->Get3DPresenter()->GetFetchObject();
const u8 bufferIndex = fetchObjMutable.GetLastFetchIndex();
fetchObjMutable.FetchFromBufferIndex(bufferIndex);
_cdv->Get3DPresenter()->LoadDisplays();
_cdv->Get3DPresenter()->ProcessDisplays();

View File

@ -92,7 +92,6 @@ private:
void __InstanceInit();
protected:
NSView *_nsView;
CALayer<DisplayViewCALayer> *_caLayer;
bool _willRenderToCALayer;
@ -100,9 +99,6 @@ public:
MacDisplayLayeredView();
MacDisplayLayeredView(ClientDisplay3DPresenter *thePresenter);
NSView* GetNSView() const;
void SetNSView(NSView *theView);
CALayer<DisplayViewCALayer>* GetCALayer() const;
bool GetRenderToCALayer() const;

View File

@ -52,21 +52,10 @@ MacDisplayLayeredView::MacDisplayLayeredView(ClientDisplay3DPresenter *thePresen
void MacDisplayLayeredView::__InstanceInit()
{
_nsView = nil;
_caLayer = nil;
_willRenderToCALayer = false;
}
NSView* MacDisplayLayeredView::GetNSView() const
{
return this->_nsView;
}
void MacDisplayLayeredView::SetNSView(NSView *theView)
{
this->_nsView = theView;
}
CALayer<DisplayViewCALayer>* MacDisplayLayeredView::GetCALayer() const
{
return this->_caLayer;

View File

@ -2055,7 +2055,6 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
if ([(MetalDisplayViewSharedData *)macSharedData device] != nil)
{
MacMetalDisplayView *macMTLCDV = new MacMetalDisplayView(macSharedData);
macMTLCDV->SetNSView(self);
macMTLCDV->Init();
localLayer = macMTLCDV->GetCALayer();
@ -2066,7 +2065,6 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
#endif
{
MacOGLDisplayView *macOGLCDV = new MacOGLDisplayView(macSharedData);
macOGLCDV->SetNSView(self);
macOGLCDV->Init();
localLayer = macOGLCDV->GetCALayer();

View File

@ -34,6 +34,15 @@ class MacMetalFetchObject;
class MacMetalDisplayPresenter;
class MacMetalDisplayView;
struct MetalProcessedFrameInfo
{
uint8_t bufferIndex;
id<MTLTexture> tex[2];
bool isMainDisplayProcessed;
bool isTouchDisplayProcessed;
};
typedef struct MetalProcessedFrameInfo MetalProcessedFrameInfo;
struct DisplayViewShaderProperties
{
float width;
@ -70,22 +79,22 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties;
id<MTLBuffer> _bufMasterBrightMode[2];
id<MTLBuffer> _bufMasterBrightIntensity[2];
id<MTLTexture> texDisplayFetch16NativeMain;
id<MTLTexture> texDisplayFetch16NativeTouch;
id<MTLTexture> texDisplayFetch32NativeMain;
id<MTLTexture> texDisplayFetch32NativeTouch;
id<MTLTexture> texDisplayFetch16CustomMain;
id<MTLTexture> texDisplayFetch16CustomTouch;
id<MTLTexture> texDisplayFetch32CustomMain;
id<MTLTexture> texDisplayFetch32CustomTouch;
id<MTLTexture> _texDisplayFetch16NativeMain;
id<MTLTexture> _texDisplayFetch16NativeTouch;
id<MTLTexture> _texDisplayFetch32NativeMain;
id<MTLTexture> _texDisplayFetch32NativeTouch;
id<MTLTexture> _texDisplayPostprocessNativeMain;
id<MTLTexture> _texDisplayPostprocessNativeTouch;
id<MTLTexture> texDisplayPostprocessNativeMain;
id<MTLTexture> texDisplayPostprocessCustomMain;
id<MTLTexture> texDisplayPostprocessNativeTouch;
id<MTLTexture> texDisplayPostprocessCustomTouch;
id<MTLTexture> _texDisplayFetch16CustomMain;
id<MTLTexture> _texDisplayFetch16CustomTouch;
id<MTLTexture> _texDisplayFetch32CustomMain;
id<MTLTexture> _texDisplayFetch32CustomTouch;
id<MTLTexture> _texDisplayPostprocessCustomMain;
id<MTLTexture> _texDisplayPostprocessCustomTouch;
id<MTLTexture> texDisplaySrcTargetMain;
id<MTLTexture> texDisplaySrcTargetTouch;
id<MTLTexture> texFetchMain;
id<MTLTexture> texFetchTouch;
id<MTLTexture> texLQ2xLUT;
id<MTLTexture> texHQ2xLUT;
@ -93,16 +102,13 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties;
id<MTLTexture> texHQ4xLUT;
id<MTLTexture> texCurrentHQnxLUT;
MTLSize fetchThreadsPerGroup;
MTLSize fetchThreadGroupsPerGridNative;
MTLSize fetchThreadGroupsPerGridCustom;
MTLSize _fetchThreadsPerGroup;
MTLSize _fetchThreadGroupsPerGridNative;
MTLSize _fetchThreadGroupsPerGridCustom;
MTLSize deposterizeThreadsPerGroup;
MTLSize deposterizeThreadGroupsPerGrid;
size_t displayFetchNativeBufferSize;
size_t displayFetchCustomBufferSize;
pthread_mutex_t _mutexFetch;
uint32_t _isUsingFramebufferDirectly[2][2];
}
@property (readonly, nonatomic) id<MTLDevice> device;
@ -117,22 +123,8 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties;
@property (readonly, nonatomic) id<MTLBuffer> hudIndexBuffer;
@property (readonly, nonatomic) id<MTLTexture> texDisplayFetch16NativeMain;
@property (readonly, nonatomic) id<MTLTexture> texDisplayFetch16NativeTouch;
@property (readonly, nonatomic) id<MTLTexture> texDisplayFetch32NativeMain;
@property (readonly, nonatomic) id<MTLTexture> texDisplayFetch32NativeTouch;
@property (retain) id<MTLTexture> texDisplayFetch16CustomMain;
@property (retain) id<MTLTexture> texDisplayFetch16CustomTouch;
@property (retain) id<MTLTexture> texDisplayFetch32CustomMain;
@property (retain) id<MTLTexture> texDisplayFetch32CustomTouch;
@property (retain) id<MTLTexture> texDisplayPostprocessNativeMain;
@property (retain) id<MTLTexture> texDisplayPostprocessCustomMain;
@property (retain) id<MTLTexture> texDisplayPostprocessNativeTouch;
@property (retain) id<MTLTexture> texDisplayPostprocessCustomTouch;
@property (retain) id<MTLTexture> texDisplaySrcTargetMain;
@property (retain) id<MTLTexture> texDisplaySrcTargetTouch;
@property (retain) id<MTLTexture> texFetchMain;
@property (retain) id<MTLTexture> texFetchTouch;
@property (readonly, nonatomic) id<MTLTexture> texLQ2xLUT;
@property (readonly, nonatomic) id<MTLTexture> texHQ2xLUT;
@ -140,16 +132,14 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties;
@property (readonly, nonatomic) id<MTLTexture> texHQ4xLUT;
@property (retain) id<MTLTexture> texCurrentHQnxLUT;
@property (assign) size_t displayFetchNativeBufferSize;
@property (assign) size_t displayFetchCustomBufferSize;
@property (readonly, nonatomic) MTLSize fetchThreadsPerGroup;
@property (readonly, nonatomic) MTLSize fetchThreadGroupsPerGridNative;
@property (assign) MTLSize fetchThreadGroupsPerGridCustom;
@property (readonly, nonatomic) MTLSize deposterizeThreadsPerGroup;
@property (readonly, nonatomic) MTLSize deposterizeThreadGroupsPerGrid;
- (void) setUsingFramebufferDirectlyAtIndex:(const u8)index displayID:(NDSDisplayID)displayID state:(bool)theState;
- (bool) isUsingFramebufferDirectlyAtIndex:(const u8)index displayID:(NDSDisplayID)displayID;
- (void) setFetchBuffersWithDisplayInfo:(const NDSDisplayInfo &)dispInfo;
- (void) setFetchTextureBindingsAtIndex:(const u8)index commandBuffer:(id<MTLCommandBuffer>)cb;
- (void) fetchFromBufferIndex:(const u8)index;
- (void) fetchNativeDisplayByID:(const NDSDisplayID)displayID bufferIndex:(const u8)bufferIndex;
- (void) fetchCustomDisplayByID:(const NDSDisplayID)displayID bufferIndex:(const u8)bufferIndex;
@ -174,15 +164,14 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties;
id<MTLBuffer> _hudVtxPositionBuffer;
id<MTLBuffer> _hudVtxColorBuffer;
id<MTLBuffer> _hudTexCoordBuffer;
id<MTLBuffer> bufCPUFilterSrcMain;
id<MTLBuffer> bufCPUFilterSrcTouch;
id<MTLBuffer> _bufCPUFilterSrcMain;
id<MTLBuffer> _bufCPUFilterSrcTouch;
id<MTLBuffer> bufCPUFilterDstMain;
id<MTLBuffer> bufCPUFilterDstTouch;
id<MTLTexture> _texDisplaySrcDeposterize[2][2];
id<MTLTexture> texDisplayPixelScaleMain;
id<MTLTexture> texDisplayPixelScaleTouch;
id<MTLTexture> _texDisplayOutput[2];
id<MTLTexture> texHUDCharMap;
MTLSize _pixelScalerThreadsPerGroup;
@ -193,28 +182,25 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties;
BOOL needsScreenVerticesUpdate;
BOOL needsHUDVerticesUpdate;
pthread_mutex_t _mutexDisplayTextureUpdate;
pthread_mutex_t _mutexBufferUpdate;
bool _needEncodeViewport;
MTLViewport _newViewport;
bool _willDrawDisplays;
bool _willDrawHUD;
bool _willDrawHUDInput;
size_t _hudStringLength;
size_t _hudTouchLineLength;
MetalProcessedFrameInfo processedFrameInfo;
}
@property (readonly, nonatomic) ClientDisplay3DPresenter *cdp;
@property (assign, nonatomic) MetalDisplayViewSharedData *sharedData;
@property (readonly, nonatomic) MTLRenderPassColorAttachmentDescriptor *colorAttachment0Desc;
@property (readonly, nonatomic) pthread_mutex_t *mutexDisplayTextureUpdate;
@property (readonly, nonatomic) pthread_mutex_t *mutexBufferUpdate;
@property (retain) id<MTLComputePipelineState> pixelScalePipeline;
@property (retain) id<MTLRenderPipelineState> outputRGBAPipeline;
@property (retain) id<MTLRenderPipelineState> outputDrawablePipeline;
@property (assign) MTLPixelFormat drawableFormat;
@property (retain) id<MTLBuffer> bufCPUFilterSrcMain;
@property (retain) id<MTLBuffer> bufCPUFilterSrcTouch;
@property (retain) id<MTLBuffer> bufCPUFilterDstMain;
@property (retain) id<MTLBuffer> bufCPUFilterDstTouch;
@property (retain) id<MTLTexture> texDisplayPixelScaleMain;
@ -226,6 +212,7 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties;
@property (assign) BOOL needsHUDVerticesUpdate;
@property (assign, nonatomic) VideoFilterTypeID pixelScaler;
@property (assign, nonatomic) OutputFilterTypeID outputFilter;
@property (assign) MetalProcessedFrameInfo processedFrameInfo;
- (id) initWithDisplayPresenter:(MacMetalDisplayPresenter *)thePresenter;
- (id<MTLCommandBuffer>) newCommandBuffer;
@ -236,7 +223,9 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties;
- (void) updateRenderBuffers;
- (void) renderForCommandBuffer:(id<MTLCommandBuffer>)cb
outputPipelineState:(id<MTLRenderPipelineState>)outputPipelineState
hudPipelineState:(id<MTLRenderPipelineState>)hudPipelineState;
hudPipelineState:(id<MTLRenderPipelineState>)hudPipelineState
texDisplayMain:(id<MTLTexture>)texDisplayMain
texDisplayTouch:(id<MTLTexture>)texDisplayTouch;
- (void) renderToBuffer:(uint32_t *)dstBuffer;
@end
@ -288,6 +277,7 @@ private:
protected:
MacMetalDisplayPresenterObject *_presenterObject;
pthread_mutex_t _mutexProcessPtr;
pthread_rwlock_t _cpuFilterRWLock[2][2];
virtual void _UpdateNormalSize();
virtual void _UpdateOrder();
@ -304,6 +294,7 @@ public:
MacMetalDisplayPresenterObject* GetPresenterObject() const;
pthread_mutex_t* GetMutexProcessPtr();
pthread_rwlock_t* GetCPUFilterRWLock(const NDSDisplayID displayID, const uint8_t bufferIndex);
virtual void Init();
virtual void SetSharedData(MacClientSharedObject *sharedObject);

View File

@ -50,6 +50,8 @@ protected:
NSOpenGLContext *_nsContext;
CGLContextObj _context;
OSSpinLock _spinlockTexFetch[2];
public:
void operator delete(void *ptr);
MacOGLClientFetchObject();
@ -60,6 +62,9 @@ public:
virtual void Init();
virtual void SetFetchBuffers(const NDSDisplayInfo &currentDisplayInfo);
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
@ -72,6 +77,7 @@ protected:
NSOpenGLPixelFormat *_nsPixelFormat;
CGLContextObj _context;
CGLPixelFormatObj _pixelFormat;
OSSpinLock _spinlockProcessedInfo;
public:
void operator delete(void *ptr);
@ -97,9 +103,13 @@ public:
virtual void LoadDisplays();
virtual void ProcessDisplays();
virtual void CopyFrameToBuffer(uint32_t *dstBuffer);
virtual void FinishFrameAtIndex(const uint8_t bufferIndex);
virtual void LockDisplayTextures();
virtual void UnlockDisplayTextures();
virtual const OGLProcessedFrameInfo& GetProcessedFrameInfo();
virtual void SetProcessedFrameInfo(const OGLProcessedFrameInfo &processedInfo);
virtual void WriteLockEmuFramebuffer(const uint8_t bufferIndex);
virtual void ReadLockEmuFramebuffer(const uint8_t bufferIndex);
virtual void UnlockEmuFramebuffer(const uint8_t bufferIndex);
};
class MacOGLDisplayView : public MacDisplayLayeredView

View File

@ -62,8 +62,8 @@
- (void)drawInCGLContext:(CGLContextObj)glContext pixelFormat:(CGLPixelFormatObj)pixelFormat forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp
{
CGLSetCurrentContext(glContext);
CGLLockContext(glContext);
CGLSetCurrentContext(glContext);
((MacOGLDisplayPresenter *)(_cdv->Get3DPresenter()))->RenderFrameOGL(false);
[super drawInCGLContext:glContext pixelFormat:pixelFormat forLayerTime:timeInterval displayTime:timeStamp];
CGLUnlockContext(glContext);
@ -156,6 +156,9 @@ MacOGLClientFetchObject::MacOGLClientFetchObject()
CGLSetCurrentContext(prevContext);
_clientData = [[MacClientSharedObject alloc] init];
_spinlockTexFetch[NDSDisplayID_Main] = OS_SPINLOCK_INIT;
_spinlockTexFetch[NDSDisplayID_Touch] = OS_SPINLOCK_INIT;
}
NSOpenGLContext* MacOGLClientFetchObject::GetNSContext() const
@ -195,12 +198,28 @@ void MacOGLClientFetchObject::FetchFromBufferIndex(const u8 index)
CGLLockContext(this->_context);
CGLSetCurrentContext(this->_context);
this->GPUClientFetchObject::FetchFromBufferIndex(index);
this->OGLClientFetchObject::FetchFromBufferIndex(index);
CGLUnlockContext(this->_context);
pthread_rwlock_unlock([sharedViewObject rwlockFramebufferAtIndex:index]);
}
GLuint MacOGLClientFetchObject::GetFetchTexture(const NDSDisplayID displayID)
{
OSSpinLockLock(&this->_spinlockTexFetch[displayID]);
const GLuint texFetchID = this->OGLClientFetchObject::GetFetchTexture(displayID);
OSSpinLockUnlock(&this->_spinlockTexFetch[displayID]);
return texFetchID;
}
void MacOGLClientFetchObject::SetFetchTexture(const NDSDisplayID displayID, GLuint texID)
{
OSSpinLockLock(&this->_spinlockTexFetch[displayID]);
this->OGLClientFetchObject::SetFetchTexture(displayID, texID);
OSSpinLockUnlock(&this->_spinlockTexFetch[displayID]);
}
#pragma mark -
void MacOGLDisplayPresenter::operator delete(void *ptr)
@ -275,6 +294,7 @@ void MacOGLDisplayPresenter::__InstanceInit(MacClientSharedObject *sharedObject)
_nsContext = nil;
_context = nil;
_spinlockProcessedInfo = OS_SPINLOCK_INIT;
if (sharedObject != nil)
{
@ -394,27 +414,41 @@ void MacOGLDisplayPresenter::CopyFrameToBuffer(uint32_t *dstBuffer)
CGLUnlockContext(this->_context);
}
void MacOGLDisplayPresenter::FinishFrameAtIndex(const uint8_t bufferIndex)
const OGLProcessedFrameInfo& MacOGLDisplayPresenter::GetProcessedFrameInfo()
{
CGLLockContext(this->_context);
CGLSetCurrentContext(this->_context);
this->OGLVideoOutput::FinishFrameAtIndex(bufferIndex);
CGLUnlockContext(this->_context);
OSSpinLockLock(&this->_spinlockProcessedInfo);
const OGLProcessedFrameInfo &processedInfo = this->OGLVideoOutput::GetProcessedFrameInfo();
OSSpinLockUnlock(&this->_spinlockProcessedInfo);
return processedInfo;
}
void MacOGLDisplayPresenter::LockDisplayTextures()
void MacOGLDisplayPresenter::SetProcessedFrameInfo(const OGLProcessedFrameInfo &processedInfo)
{
OSSpinLockLock(&this->_spinlockProcessedInfo);
this->OGLVideoOutput::SetProcessedFrameInfo(processedInfo);
OSSpinLockUnlock(&this->_spinlockProcessedInfo);
}
void MacOGLDisplayPresenter::WriteLockEmuFramebuffer(const uint8_t bufferIndex)
{
const GPUClientFetchObject &fetchObj = this->GetFetchObject();
MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)fetchObj.GetClientData();
pthread_rwlock_wrlock([sharedViewObject rwlockFramebufferAtIndex:bufferIndex]);
}
void MacOGLDisplayPresenter::ReadLockEmuFramebuffer(const uint8_t bufferIndex)
{
const GPUClientFetchObject &fetchObj = this->GetFetchObject();
const u8 bufferIndex = this->_emuDisplayInfo.bufferIndex;
MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)fetchObj.GetClientData();
pthread_rwlock_rdlock([sharedViewObject rwlockFramebufferAtIndex:bufferIndex]);
}
void MacOGLDisplayPresenter::UnlockDisplayTextures()
void MacOGLDisplayPresenter::UnlockEmuFramebuffer(const uint8_t bufferIndex)
{
const GPUClientFetchObject &fetchObj = this->GetFetchObject();
const u8 bufferIndex = this->_emuDisplayInfo.bufferIndex;
MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)fetchObj.GetClientData();
pthread_rwlock_unlock([sharedViewObject rwlockFramebufferAtIndex:bufferIndex]);
@ -460,14 +494,14 @@ bool MacOGLDisplayView::GetViewNeedsFlush()
void MacOGLDisplayView::SetViewNeedsFlush()
{
if (!this->_allowViewUpdates || (this->_presenter == nil) || (this->GetNSView() == nil))
if (!this->_allowViewUpdates || (this->_presenter == nil) || (this->_caLayer == nil))
{
return;
}
if (this->GetRenderToCALayer())
{
[[this->GetNSView() layer] setNeedsDisplay];
[this->_caLayer setNeedsDisplay];
}
else
{

View File

@ -119,6 +119,19 @@ bool IsOSXVersionSupported(const unsigned int major, const unsigned int minor, c
return result;
}
bool IsOSXVersion(const unsigned int major, const unsigned int minor, const unsigned int revision)
{
bool result = false;
if (!isSystemVersionAlreadyRead)
{
ReadSystemVersionPListFile();
}
result = (isSystemVersionAlreadyRead && (OSXVersionMajor == major) && (OSXVersionMinor == minor) && (OSXVersionRevision == revision));
return result;
}
/********************************************************************************************
GetNearestPositivePOT()

View File

@ -27,6 +27,7 @@ extern "C"
#endif
bool IsOSXVersionSupported(const unsigned int major, const unsigned int minor, const unsigned int revision);
bool IsOSXVersion(const unsigned int major, const unsigned int minor, const unsigned int revision);
uint32_t GetNearestPositivePOT(uint32_t value);
#ifdef __cplusplus