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:
parent
57f5fa0e6e
commit
89a74e5c3e
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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 ¤tDisplayInfo)
|
void OGLClientFetchObject::SetFetchBuffers(const NDSDisplayInfo ¤tDisplayInfo)
|
||||||
{
|
{
|
||||||
|
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 ¤tDisplayI
|
||||||
|
|
||||||
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 ¤tDisplayI
|
||||||
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 ¤tDisplayInfo = 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));
|
|
||||||
}
|
|
||||||
|
|
|
@ -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 ¤tDisplayInfo);
|
virtual void SetFetchBuffers(const NDSDisplayInfo ¤tDisplayInfo);
|
||||||
|
virtual void FetchFromBufferIndex(const u8 index);
|
||||||
|
|
||||||
|
virtual GLuint GetFetchTexture(const NDSDisplayID displayID);
|
||||||
|
virtual void SetFetchTexture(const NDSDisplayID displayID, GLuint texID);
|
||||||
};
|
};
|
||||||
|
|
||||||
class 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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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 ¤tDisplayInfo);
|
virtual void SetFetchBuffers(const NDSDisplayInfo ¤tDisplayInfo);
|
||||||
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
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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()
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue