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_Main] = ClientDisplaySource_DeterminedByNDS;
_displaySourceSelect[NDSDisplayID_Touch] = ClientDisplaySource_DeterminedByNDS; _displaySourceSelect[NDSDisplayID_Touch] = ClientDisplaySource_DeterminedByNDS;
_isSelectedDisplayEnabled[NDSDisplayID_Main] = true; _isSelectedDisplayEnabled[NDSDisplayID_Main] = false;
_isSelectedDisplayEnabled[NDSDisplayID_Touch] = true; _isSelectedDisplayEnabled[NDSDisplayID_Touch] = false;
_selectedSourceForDisplay[NDSDisplayID_Main] = NDSDisplayID_Main; _selectedSourceForDisplay[NDSDisplayID_Main] = NDSDisplayID_Main;
_selectedSourceForDisplay[NDSDisplayID_Touch] = NDSDisplayID_Touch; _selectedSourceForDisplay[NDSDisplayID_Touch] = NDSDisplayID_Touch;
@ -820,7 +820,7 @@ void ClientDisplayPresenter::LoadDisplays()
case ClientDisplaySource_EngineMain: 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->_selectedSourceForDisplay[NDSDisplayID_Main] = NDSDisplayID_Main;
this->_isSelectedDisplayEnabled[NDSDisplayID_Main] = this->_emuDisplayInfo.isDisplayEnabled[NDSDisplayID_Main]; this->_isSelectedDisplayEnabled[NDSDisplayID_Main] = this->_emuDisplayInfo.isDisplayEnabled[NDSDisplayID_Main];
@ -835,7 +835,7 @@ void ClientDisplayPresenter::LoadDisplays()
case ClientDisplaySource_EngineSub: 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->_selectedSourceForDisplay[NDSDisplayID_Main] = NDSDisplayID_Main;
this->_isSelectedDisplayEnabled[NDSDisplayID_Main] = this->_emuDisplayInfo.isDisplayEnabled[NDSDisplayID_Main]; this->_isSelectedDisplayEnabled[NDSDisplayID_Main] = this->_emuDisplayInfo.isDisplayEnabled[NDSDisplayID_Main];
@ -863,7 +863,7 @@ void ClientDisplayPresenter::LoadDisplays()
case ClientDisplaySource_EngineMain: 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->_selectedSourceForDisplay[NDSDisplayID_Touch] = NDSDisplayID_Touch;
this->_isSelectedDisplayEnabled[NDSDisplayID_Touch] = this->_emuDisplayInfo.isDisplayEnabled[NDSDisplayID_Touch]; this->_isSelectedDisplayEnabled[NDSDisplayID_Touch] = this->_emuDisplayInfo.isDisplayEnabled[NDSDisplayID_Touch];
@ -878,7 +878,7 @@ void ClientDisplayPresenter::LoadDisplays()
case ClientDisplaySource_EngineSub: 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->_selectedSourceForDisplay[NDSDisplayID_Touch] = NDSDisplayID_Touch;
this->_isSelectedDisplayEnabled[NDSDisplayID_Touch] = this->_emuDisplayInfo.isDisplayEnabled[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. // Do nothing. This is implementation dependent.
} }
void ClientDisplayPresenter::FinishFrameAtIndex(const uint8_t bufferIndex)
{
// Do nothing. This is implementation dependent.
}
const NDSDisplayInfo& ClientDisplayPresenter::GetEmuDisplayInfo() const const NDSDisplayInfo& ClientDisplayPresenter::GetEmuDisplayInfo() const
{ {
return this->_emuDisplayInfo; return this->_emuDisplayInfo;

View File

@ -301,7 +301,6 @@ public:
virtual void LoadDisplays(); virtual void LoadDisplays();
virtual void ProcessDisplays(); virtual void ProcessDisplays();
virtual void UpdateLayout(); virtual void UpdateLayout();
virtual void FinishFrameAtIndex(const uint8_t bufferIndex);
virtual void CopyFrameToBuffer(uint32_t *dstBuffer); 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_Main][1], NULL);
pthread_rwlock_init(&_srcCloneRWLock[NDSDisplayID_Touch][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)); _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_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); _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_Touch][0]);
pthread_rwlock_destroy(&this->_srcCloneRWLock[NDSDisplayID_Main][1]); pthread_rwlock_destroy(&this->_srcCloneRWLock[NDSDisplayID_Main][1]);
pthread_rwlock_destroy(&this->_srcCloneRWLock[NDSDisplayID_Touch][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 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() void OGLClientFetchObject::Init()
{ {
glGenTextures(4, &this->_texDisplayFetchNative[0][0]); glGenTextures(4, &this->_texDisplayFetchNative[0][0]);
@ -4738,6 +4759,9 @@ void OGLClientFetchObject::Init()
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); 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()) if (this->_contextInfo->IsShaderSupported())
{ {
SetupHQnxLUTs_OGL(GL_TEXTURE0 + 1, this->_texLQ2xLUT, this->_texHQ2xLUT, this->_texHQ3xLUT, this->_texHQ4xLUT); 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) 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 #ifdef MSB_FIRST
this->_fetchColorFormatOGL = (currentDisplayInfo.pixelBytes == 2) ? GL_UNSIGNED_SHORT_1_5_5_5_REV : GL_UNSIGNED_INT_8_8_8_8; this->_fetchColorFormatOGL = (currentDisplayInfo.pixelBytes == 2) ? GL_UNSIGNED_SHORT_1_5_5_5_REV : GL_UNSIGNED_INT_8_8_8_8;
#else #else
this->_fetchColorFormatOGL = (currentDisplayInfo.pixelBytes == 2) ? GL_UNSIGNED_SHORT_1_5_5_5_REV : GL_UNSIGNED_INT_8_8_8_8_REV; this->_fetchColorFormatOGL = (currentDisplayInfo.pixelBytes == 2) ? GL_UNSIGNED_SHORT_1_5_5_5_REV : GL_UNSIGNED_INT_8_8_8_8_REV;
#endif #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(); glFinish();
glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_ARB, currentDisplayInfo.framebufferSize * 2, currentDisplayInfo.masterFramebufferHead); 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]); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texDisplayFetchNative[NDSDisplayID_Main][0]);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_SHARED_APPLE); 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]); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texDisplayFetchNative[NDSDisplayID_Main][1]);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_SHARED_APPLE); 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]); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texDisplayFetchNative[NDSDisplayID_Touch][0]);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_SHARED_APPLE); 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]); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texDisplayFetchNative[NDSDisplayID_Touch][1]);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_SHARED_APPLE); 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]); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texDisplayFetchCustom[NDSDisplayID_Main][0]);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_SHARED_APPLE); 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]); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texDisplayFetchCustom[NDSDisplayID_Main][1]);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_SHARED_APPLE); 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]); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texDisplayFetchCustom[NDSDisplayID_Touch][0]);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_SHARED_APPLE); 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]); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texDisplayFetchCustom[NDSDisplayID_Touch][1]);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_SHARED_APPLE); 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); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
@ -4818,6 +4855,45 @@ void OGLClientFetchObject::SetFetchBuffers(const NDSDisplayInfo &currentDisplayI
pthread_rwlock_unlock(&this->_srcCloneRWLock[NDSDisplayID_Touch][1]); 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) void OGLClientFetchObject::_FetchNativeDisplayByID(const NDSDisplayID displayID, const u8 bufferIndex)
{ {
pthread_rwlock_wrlock(&this->_srcCloneRWLock[displayID][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]); 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 - #pragma mark -
OGLVideoOutput::OGLVideoOutput() OGLVideoOutput::OGLVideoOutput()
@ -4854,6 +4940,12 @@ OGLVideoOutput::OGLVideoOutput()
_texCPUFilterDstID[NDSDisplayID_Touch] = 0; _texCPUFilterDstID[NDSDisplayID_Touch] = 0;
_fboFrameCopyID = 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 = new std::vector<OGLVideoLayer *>;
_layerList->reserve(8); _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) void OGLVideoOutput::CopyFrameToBuffer(uint32_t *dstBuffer)
{ {
GLuint texFrameCopyID = 0; 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. // 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. // Do nothing. This is implementation dependent.
} }
@ -6568,8 +6662,10 @@ OGLDisplayLayer::OGLDisplayLayer(OGLVideoOutput *oglVO)
_displayTexFilter[0] = GL_NEAREST; _displayTexFilter[0] = GL_NEAREST;
_displayTexFilter[1] = GL_NEAREST; _displayTexFilter[1] = GL_NEAREST;
_texVideoOutputID[0] = 0; pthread_rwlock_init(&_cpuFilterRWLock[NDSDisplayID_Main][0], NULL);
_texVideoOutputID[1] = 0; 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 // Set up VBOs
glGenBuffersARB(1, &_vboVertexID); glGenBuffersARB(1, &_vboVertexID);
@ -6676,6 +6772,11 @@ OGLDisplayLayer::~OGLDisplayLayer()
delete this->_shaderFilter[0]; delete this->_shaderFilter[0];
delete this->_shaderFilter[1]; 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() void OGLDisplayLayer::_UpdateRotationScaleOGL()
@ -7062,110 +7163,237 @@ void OGLDisplayLayer::LoadNativeDisplayByID_OGL(const NDSDisplayID displayID)
OGLClientFetchObject &fetchObjMutable = (OGLClientFetchObject &)this->_output->GetFetchObject(); OGLClientFetchObject &fetchObjMutable = (OGLClientFetchObject &)this->_output->GetFetchObject();
VideoFilter *vf = this->_output->GetPixelScalerObject(displayID); 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) pthread_rwlock_wrlock(&this->_cpuFilterRWLock[displayID][bufferIndex]);
{ fetchObjMutable.CopyFromSrcClone(vf->GetSrcBufferPtr(), displayID, bufferIndex);
VideoFilter *vf = this->_output->GetPixelScalerObject(displayID); pthread_rwlock_unlock(&this->_cpuFilterRWLock[displayID][bufferIndex]);
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();
}
} }
} }
void OGLDisplayLayer::ProcessOGL() 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 NDSDisplayInfo &emuDisplayInfo = this->_output->GetEmuDisplayInfo();
const ClientDisplayMode mode = this->_output->GetPresenterProperties().mode; 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 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]] }; 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 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]] }; 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 // Run the video source filters and the pixel scalers
const bool willFilterOnGPU = this->_output->WillFilterOnGPU(); const bool willFilterOnGPU = this->_output->WillFilterOnGPU();
const bool useDeposterize = this->_output->GetSourceDeposterize(); const bool shouldProcessDisplay[2] = { (didRenderNative[NDSDisplayID_Main] || !emuDisplayInfo.isCustomSizeRequested) && this->_output->IsSelectedDisplayEnabled(NDSDisplayID_Main) && (mode == ClientDisplayMode_Main || mode == ClientDisplayMode_Dual),
const bool needProcessDisplay[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]) };
(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);
}
// 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)
{
fetchObj.FetchTextureUnlock(NDSDisplayID_Main);
}
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->_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);
}
} }
if (needProcessDisplay[NDSDisplayID_Touch]) // Run the pixel scalers. First attempt on the GPU.
if ( (this->_output->GetPixelScaler() != VideoFilterTypeID_None) && willFilterOnGPU )
{ {
this->_ProcessDisplayByID(NDSDisplayID_Touch, width[NDSDisplayID_Touch], height[NDSDisplayID_Touch], texVideoSourceID[NDSDisplayID_Touch]); 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 (needsLock) // 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 )
{ {
this->_output->UnlockDisplayTextures(); 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 // 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]; texTouch = texMain;
}
else
{
this->_texVideoOutputID[NDSDisplayID_Touch] = texVideoSourceID[NDSDisplayID_Main];
width[NDSDisplayID_Touch] = width[NDSDisplayID_Main]; width[NDSDisplayID_Touch] = width[NDSDisplayID_Main];
height[NDSDisplayID_Touch] = height[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. // OpenGL shader-based filters can modify the viewport, so it needs to be reset here.
glViewport(0, 0, this->_output->GetViewportWidth(), this->_output->GetViewportHeight()); 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) void OGLDisplayLayer::RenderOGL(bool isRenderingFlipped)
{ {
const NDSDisplayInfo &emuDisplayInfo = this->_output->GetEmuDisplayInfo();
const bool isShaderSupported = this->_output->GetContextInfo()->IsShaderSupported(); const bool isShaderSupported = this->_output->GetContextInfo()->IsShaderSupported();
if (isShaderSupported) if (isShaderSupported)
@ -7227,124 +7465,198 @@ void OGLDisplayLayer::RenderOGL(bool isRenderingFlipped)
this->_UpdateRotationScaleOGL(); this->_UpdateRotationScaleOGL();
} }
if (emuDisplayInfo.pixelBytes != 0) if (this->_needUpdateVertices)
{ {
if (this->_needUpdateVertices) this->_UpdateVerticesOGL();
}
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)
{
case ClientDisplayMode_Main:
{ {
this->_UpdateVerticesOGL(); if (this->_output->IsSelectedDisplayEnabled(NDSDisplayID_Main))
{
if (isShaderSupported)
{
glUniform1f(this->_uniformBacklightIntensity, backlightIntensity[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;
} }
this->_output->LockDisplayTextures(); case ClientDisplayMode_Touch:
glBindVertexArrayDESMUME(this->_vaoMainStatesID);
switch (this->_output->GetPresenterProperties().mode)
{ {
case ClientDisplayMode_Main: if (this->_output->IsSelectedDisplayEnabled(NDSDisplayID_Touch))
{ {
if (this->_output->IsSelectedDisplayEnabled(NDSDisplayID_Main)) if (isShaderSupported)
{ {
if (isShaderSupported) glUniform1f(this->_uniformBacklightIntensity, backlightIntensity[NDSDisplayID_Touch]);
{
glUniform1f(this->_uniformBacklightIntensity, emuDisplayInfo.backlightIntensity[NDSDisplayID_Main]);
}
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoOutputID[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);
} }
break;
}
case ClientDisplayMode_Touch: if (texFetchTouchNeedsLock)
{
if (this->_output->IsSelectedDisplayEnabled(NDSDisplayID_Touch))
{ {
if (isShaderSupported) fetchObj.FetchTextureWriteLock(NDSDisplayID_Touch);
{
glUniform1f(this->_uniformBacklightIntensity, emuDisplayInfo.backlightIntensity[NDSDisplayID_Touch]);
}
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoOutputID[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);
} }
break;
}
case ClientDisplayMode_Dual: glBindTexture(GL_TEXTURE_RECTANGLE_ARB, processedInfo.texID[NDSDisplayID_Touch]);
{ glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, this->_displayTexFilter[NDSDisplayID_Touch]);
const NDSDisplayID majorDisplayID = (this->_output->GetPresenterProperties().order == ClientDisplayOrder_MainFirst) ? NDSDisplayID_Main : NDSDisplayID_Touch; glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, this->_displayTexFilter[NDSDisplayID_Touch]);
const size_t majorDisplayVtx = (this->_output->GetPresenterProperties().order == ClientDisplayOrder_MainFirst) ? 8 : 12; glDrawArrays(GL_TRIANGLE_STRIP, 4, 4);
switch (this->_output->GetPresenterProperties().layout) if (texFetchTouchNeedsLock)
{ {
case ClientDisplayLayout_Hybrid_2_1: glFlush();
case ClientDisplayLayout_Hybrid_16_9: fetchObj.FetchTextureUnlock(NDSDisplayID_Touch);
case ClientDisplayLayout_Hybrid_16_10: texFetchTouchNeedsLock = false;
}
}
break;
}
case ClientDisplayMode_Dual:
{
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:
case ClientDisplayLayout_Hybrid_16_9:
case ClientDisplayLayout_Hybrid_16_10:
{
if (this->_output->IsSelectedDisplayEnabled(majorDisplayID))
{ {
if (this->_output->IsSelectedDisplayEnabled(majorDisplayID)) if (isShaderSupported)
{ {
if (isShaderSupported) glUniform1f(this->_uniformBacklightIntensity, backlightIntensity[majorDisplayID]);
{
glUniform1f(this->_uniformBacklightIntensity, emuDisplayInfo.backlightIntensity[majorDisplayID]);
}
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoOutputID[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);
} }
break;
}
default: const bool texFetchMajorNeedsLock = (majorDisplayID == NDSDisplayID_Main) ? texFetchMainNeedsLock : texFetchTouchNeedsLock;
break;
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;
} }
if (this->_output->IsSelectedDisplayEnabled(NDSDisplayID_Main)) default:
{ break;
if (isShaderSupported) }
{
glUniform1f(this->_uniformBacklightIntensity, emuDisplayInfo.backlightIntensity[NDSDisplayID_Main]);
}
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoOutputID[NDSDisplayID_Main]); if (this->_output->IsSelectedDisplayEnabled(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]); if (isShaderSupported)
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); {
glUniform1f(this->_uniformBacklightIntensity, backlightIntensity[NDSDisplayID_Main]);
} }
if (this->_output->IsSelectedDisplayEnabled(NDSDisplayID_Touch)) if (texFetchMainNeedsLock && !texFetchMainAlreadyLocked)
{ {
if (isShaderSupported) fetchObj.FetchTextureWriteLock(NDSDisplayID_Main);
{ }
glUniform1f(this->_uniformBacklightIntensity, emuDisplayInfo.backlightIntensity[NDSDisplayID_Touch]);
}
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoOutputID[NDSDisplayID_Touch]); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, processedInfo.texID[NDSDisplayID_Main]);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, this->_displayTexFilter[NDSDisplayID_Touch]); 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_Touch]); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, this->_displayTexFilter[NDSDisplayID_Main]);
glDrawArrays(GL_TRIANGLE_STRIP, 4, 4); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
if (texFetchMainNeedsLock)
{
glFlush();
fetchObj.FetchTextureUnlock(NDSDisplayID_Main);
texFetchMainNeedsLock = false;
} }
} }
default: if (this->_output->IsSelectedDisplayEnabled(NDSDisplayID_Touch))
break; {
if (isShaderSupported)
{
glUniform1f(this->_uniformBacklightIntensity, backlightIntensity[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;
}
}
} }
glBindVertexArrayDESMUME(0); default:
this->_output->UnlockDisplayTextures(); break;
}
glBindVertexArrayDESMUME(0);
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, ShaderSupport_FutureTier = 6,
}; };
struct OGLProcessedFrameInfo
{
uint8_t bufferIndex;
GLuint texID[2];
bool isMainDisplayProcessed;
bool isTouchDisplayProcessed;
};
typedef struct OGLProcessedFrameInfo OGLProcessedFrameInfo;
class OGLContextInfo class OGLContextInfo
{ {
protected: protected:
@ -273,7 +282,6 @@ public:
virtual void SetVisibility(const bool visibleState); virtual void SetVisibility(const bool visibleState);
virtual void RenderOGL(bool isRenderingFlipped) = 0; virtual void RenderOGL(bool isRenderingFlipped) = 0;
virtual void FinishOGL(const u8 bufferIndex) {};
}; };
class OGLHUDLayer : public OGLVideoLayer class OGLHUDLayer : public OGLVideoLayer
@ -306,8 +314,7 @@ protected:
OGLFilter *_filterDeposterize[2]; OGLFilter *_filterDeposterize[2];
OGLFilter *_shaderFilter[2]; OGLFilter *_shaderFilter[2];
GLint _displayTexFilter[2]; GLint _displayTexFilter[2];
pthread_rwlock_t _cpuFilterRWLock[2][2];
GLuint _texVideoOutputID[2];
GLuint _vaoMainStatesID; GLuint _vaoMainStatesID;
GLuint _vboVertexID; GLuint _vboVertexID;
@ -316,8 +323,6 @@ protected:
void _UpdateRotationScaleOGL(); void _UpdateRotationScaleOGL();
void _UpdateVerticesOGL(); void _UpdateVerticesOGL();
void _ProcessDisplayByID(const NDSDisplayID displayID, GLsizei &inoutWidth, GLsizei &inoutHeight, GLuint &inoutTexID);
public: public:
OGLDisplayLayer() {}; OGLDisplayLayer() {};
OGLDisplayLayer(OGLVideoOutput *oglVO); OGLDisplayLayer(OGLVideoOutput *oglVO);
@ -328,8 +333,8 @@ public:
void LoadNativeDisplayByID_OGL(const NDSDisplayID displayID); void LoadNativeDisplayByID_OGL(const NDSDisplayID displayID);
void ProcessOGL(); void ProcessOGL();
virtual void RenderOGL(bool isRenderingFlipped); virtual void RenderOGL(bool isRenderingFlipped);
virtual void FinishOGL(const u8 bufferIndex);
}; };
class OGLClientFetchObject : public GPUClientFetchObject class OGLClientFetchObject : public GPUClientFetchObject
@ -345,10 +350,13 @@ protected:
GLuint _texHQ3xLUT; GLuint _texHQ3xLUT;
GLuint _texHQ4xLUT; GLuint _texHQ4xLUT;
GLuint _texFetch[2];
bool _useDirectToCPUFilterPipeline; bool _useDirectToCPUFilterPipeline;
uint32_t *_srcNativeCloneMaster; uint32_t *_srcNativeCloneMaster;
uint32_t *_srcNativeClone[2][2]; uint32_t *_srcNativeClone[2][2];
pthread_rwlock_t _srcCloneRWLock[2][2]; pthread_rwlock_t _srcCloneRWLock[2][2];
pthread_rwlock_t _texFetchRWLock[2];
bool _srcCloneNeedsUpdate[2][2]; bool _srcCloneNeedsUpdate[2][2];
virtual void _FetchNativeDisplayByID(const NDSDisplayID displayID, const u8 bufferIndex); 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 CopyFromSrcClone(uint32_t *dstBufferPtr, const NDSDisplayID displayID, const u8 bufferIndex);
void FetchNativeDisplayToSrcClone(const NDSDisplayID displayID, const u8 bufferIndex, bool needsLock); 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 Init();
virtual void SetFetchBuffers(const NDSDisplayInfo &currentDisplayInfo); 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 class OGLVideoOutput : public ClientDisplay3DPresenter
@ -389,6 +404,8 @@ protected:
GLuint _texCPUFilterDstID[2]; GLuint _texCPUFilterDstID[2];
GLuint _fboFrameCopyID; GLuint _fboFrameCopyID;
OGLProcessedFrameInfo _processedFrameInfo;
std::vector<OGLVideoLayer *> *_layerList; std::vector<OGLVideoLayer *> *_layerList;
void _UpdateViewport(); void _UpdateViewport();
@ -428,11 +445,15 @@ public:
// Client view interface // Client view interface
virtual void ProcessDisplays(); 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 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); extern void (*glBindVertexArrayDESMUME)(GLuint id);

View File

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

View File

@ -167,16 +167,21 @@ public:
#ifdef ENABLE_APPLE_METAL #ifdef ENABLE_APPLE_METAL
if (IsOSXVersionSupported(10, 11, 0) && ![[NSUserDefaults standardUserDefaults] boolForKey:@"Debug_DisableMetal"]) if (IsOSXVersionSupported(10, 11, 0) && ![[NSUserDefaults standardUserDefaults] boolForKey:@"Debug_DisableMetal"])
{ {
fetchObject = new MacMetalFetchObject; // 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;
if (fetchObject->GetClientData() == nil) if (fetchObject->GetClientData() == nil)
{ {
delete fetchObject; delete fetchObject;
fetchObject = NULL; fetchObject = NULL;
} }
else else
{ {
GPU->SetWillPostprocessDisplays(false); GPU->SetWillPostprocessDisplays(false);
}
} }
} }
#endif #endif
@ -189,6 +194,8 @@ public:
fetchObject->Init(); fetchObject->Init();
gpuEvent->SetFetchObject(fetchObject); gpuEvent->SetFetchObject(fetchObject);
[self clearWithColor:0x8000];
return self; return self;
} }
@ -244,15 +251,16 @@ public:
- (void) setGpuDimensions:(NSSize)theDimensions - (void) setGpuDimensions:(NSSize)theDimensions
{ {
[[self sharedData] finishAllDisplayViewsAtIndex:0];
[[self sharedData] finishAllDisplayViewsAtIndex:1];
gpuEvent->Render3DLock(); gpuEvent->Render3DLock();
gpuEvent->FramebufferLockWrite(); gpuEvent->FramebufferLockWrite();
pthread_rwlock_wrlock([[self sharedData] rwlockFramebufferAtIndex:0]);
pthread_rwlock_wrlock([[self sharedData] rwlockFramebufferAtIndex:1]);
GPU->SetCustomFramebufferSize(theDimensions.width, theDimensions.height); GPU->SetCustomFramebufferSize(theDimensions.width, theDimensions.height);
fetchObject->SetFetchBuffers(GPU->GetDisplayInfo()); fetchObject->SetFetchBuffers(GPU->GetDisplayInfo());
pthread_rwlock_unlock([[self sharedData] rwlockFramebufferAtIndex:1]);
pthread_rwlock_unlock([[self sharedData] rwlockFramebufferAtIndex:0]);
gpuEvent->FramebufferUnlock(); gpuEvent->FramebufferUnlock();
gpuEvent->Render3DUnlock(); gpuEvent->Render3DUnlock();
} }
@ -294,15 +302,16 @@ public:
} }
// Change the color format. // Change the color format.
[[self sharedData] finishAllDisplayViewsAtIndex:0];
[[self sharedData] finishAllDisplayViewsAtIndex:1];
gpuEvent->Render3DLock(); gpuEvent->Render3DLock();
gpuEvent->FramebufferLockWrite(); gpuEvent->FramebufferLockWrite();
pthread_rwlock_wrlock([[self sharedData] rwlockFramebufferAtIndex:0]);
pthread_rwlock_wrlock([[self sharedData] rwlockFramebufferAtIndex:1]);
GPU->SetColorFormat((NDSColorFormat)colorFormat); GPU->SetColorFormat((NDSColorFormat)colorFormat);
fetchObject->SetFetchBuffers(GPU->GetDisplayInfo()); fetchObject->SetFetchBuffers(GPU->GetDisplayInfo());
pthread_rwlock_unlock([[self sharedData] rwlockFramebufferAtIndex:1]);
pthread_rwlock_unlock([[self sharedData] rwlockFramebufferAtIndex:0]);
gpuEvent->FramebufferUnlock(); gpuEvent->FramebufferUnlock();
gpuEvent->Render3DUnlock(); gpuEvent->Render3DUnlock();
} }
@ -842,8 +851,17 @@ public:
- (void) clearWithColor:(const uint16_t)colorBGRA5551 - (void) clearWithColor:(const uint16_t)colorBGRA5551
{ {
gpuEvent->FramebufferLockWrite(); gpuEvent->FramebufferLockWrite();
const u8 bufferIndex = GPU->GetDisplayInfo().bufferIndex;
pthread_rwlock_wrlock([[self sharedData] rwlockFramebufferAtIndex:bufferIndex]);
GPU->ClearWithColor(colorBGRA5551); GPU->ClearWithColor(colorBGRA5551);
pthread_rwlock_unlock([[self sharedData] rwlockFramebufferAtIndex:bufferIndex]);
gpuEvent->FramebufferUnlock(); gpuEvent->FramebufferUnlock();
#if !defined(PORT_VERSION_OPENEMU)
[[self sharedData] signalFetchAtIndex:bufferIndex];
#endif
} }
- (void) respondToPauseState:(BOOL)isPaused - (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 - (void) flushAllDisplaysOnDisplayLink:(CVDisplayLinkRef)displayLink timeStamp:(const CVTimeStamp *)timeStamp
{ {
pthread_mutex_t *currentMutex = _mutexOutputList; pthread_mutex_t *currentMutex = _mutexOutputList;
@ -1190,10 +1184,10 @@ public:
- (void) runFetchLoop - (void) runFetchLoop
{ {
pthread_mutex_lock(&_mutexFetchExecute);
do do
{ {
pthread_mutex_lock(&_mutexFetchExecute);
while (!_isFetchSignalled) while (!_isFetchSignalled)
{ {
pthread_cond_wait(&_condSignalFetch, &_mutexFetchExecute); pthread_cond_wait(&_condSignalFetch, &_mutexFetchExecute);
@ -1202,8 +1196,6 @@ public:
GPUFetchObject->FetchFromBufferIndex(_fetchIndex); GPUFetchObject->FetchFromBufferIndex(_fetchIndex);
[self pushVideoDataToAllDisplayViews]; [self pushVideoDataToAllDisplayViews];
pthread_mutex_unlock(&_mutexFetchExecute);
} while(true); } while(true);
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -119,6 +119,19 @@ bool IsOSXVersionSupported(const unsigned int major, const unsigned int minor, c
return result; 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() GetNearestPositivePOT()

View File

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