Cocoa Port: The Metal blitter now performs its own display postprocessing instead of letting the GPUSubsystem do it.
- Display views now take the Deposterize filter into account when determining the direct-to-CPU-filtering state. - GPUSubsystem now combines the RGB666-to-RGB888 conversions and master brightness steps into a single postprocessing step. - Do some minor code cleanup.
This commit is contained in:
parent
b553ff917b
commit
093ce4b05d
|
@ -1382,7 +1382,7 @@ void GPUEngineBase::UpdatePropertiesWithoutRender(const u16 l)
|
|||
}
|
||||
}
|
||||
|
||||
void GPUEngineBase::FramebufferPostprocess()
|
||||
void GPUEngineBase::LastLineProcess()
|
||||
{
|
||||
this->RefreshAffineStartRegs();
|
||||
}
|
||||
|
@ -4024,69 +4024,66 @@ void GPUEngineBase::SetWillApplyMasterBrightnessPerScanline(bool willApply)
|
|||
this->_willApplyMasterBrightnessPerScanline = willApply;
|
||||
}
|
||||
|
||||
template <NDSColorFormat OUTPUTFORMAT>
|
||||
void GPUEngineBase::ApplyMasterBrightness()
|
||||
void GPUEngineBase::UpdateMasterBrightnessDisplayInfo(NDSDisplayInfo &mutableInfo)
|
||||
{
|
||||
NDSDisplayInfo &dispInfoMutable = (NDSDisplayInfo &)GPU->GetDisplayInfo();
|
||||
const bool isMasterBrightnessAutoApplied = GPU->GetWillAutoApplyMasterBrightness();
|
||||
|
||||
if (this->_willApplyMasterBrightnessPerScanline)
|
||||
{
|
||||
const bool isNativeSize = (this->nativeLineOutputCount == GPU_FRAMEBUFFER_NATIVE_HEIGHT);
|
||||
bool needsApply = false;
|
||||
|
||||
for (size_t line = 0; line < GPU_FRAMEBUFFER_NATIVE_HEIGHT; line++)
|
||||
{
|
||||
const GPUEngineCompositorInfo &compInfo = this->_currentCompositorInfo[line];
|
||||
|
||||
if (isMasterBrightnessAutoApplied)
|
||||
{
|
||||
void *dstColorLine = (isNativeSize) ? ((u8 *)this->nativeBuffer + (compInfo.line.blockOffsetNative * dispInfoMutable.pixelBytes)) : ((u8 *)this->customBuffer + (compInfo.line.blockOffsetCustom * dispInfoMutable.pixelBytes));
|
||||
const size_t pixCount = (isNativeSize) ? GPU_FRAMEBUFFER_NATIVE_WIDTH : compInfo.line.pixelCount;
|
||||
|
||||
this->ApplyMasterBrightness<OUTPUTFORMAT, false>(dstColorLine,
|
||||
pixCount,
|
||||
compInfo.renderState.masterBrightnessMode,
|
||||
compInfo.renderState.masterBrightnessIntensity);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( (compInfo.renderState.masterBrightnessIntensity != 0) && ((compInfo.renderState.masterBrightnessMode == GPUMasterBrightMode_Up) || (compInfo.renderState.masterBrightnessMode == GPUMasterBrightMode_Down)) )
|
||||
{
|
||||
needsApply = true;
|
||||
}
|
||||
|
||||
mutableInfo.masterBrightnessMode[this->_targetDisplayID][line] = compInfo.renderState.masterBrightnessMode;
|
||||
mutableInfo.masterBrightnessIntensity[this->_targetDisplayID][line] = compInfo.renderState.masterBrightnessIntensity;
|
||||
}
|
||||
|
||||
dispInfoMutable.masterBrightnessMode[this->_targetDisplayID][line] = compInfo.renderState.masterBrightnessMode;
|
||||
dispInfoMutable.masterBrightnessIntensity[this->_targetDisplayID][line] = compInfo.renderState.masterBrightnessIntensity;
|
||||
}
|
||||
|
||||
dispInfoMutable.needApplyMasterBrightness[this->_targetDisplayID] = dispInfoMutable.needApplyMasterBrightness[this->_targetDisplayID] && needsApply;
|
||||
mutableInfo.needApplyMasterBrightness[this->_targetDisplayID] = needsApply;
|
||||
}
|
||||
else
|
||||
{
|
||||
const GPUEngineCompositorInfo &compInfo = this->_currentCompositorInfo[0];
|
||||
|
||||
if (isMasterBrightnessAutoApplied)
|
||||
{
|
||||
this->ApplyMasterBrightness<OUTPUTFORMAT, false>(this->renderedBuffer,
|
||||
this->renderedWidth * this->renderedHeight,
|
||||
compInfo.renderState.masterBrightnessMode,
|
||||
compInfo.renderState.masterBrightnessIntensity);
|
||||
}
|
||||
else
|
||||
{
|
||||
dispInfoMutable.needApplyMasterBrightness[this->_targetDisplayID] = (compInfo.renderState.masterBrightnessIntensity != 0) && ((compInfo.renderState.masterBrightnessMode == GPUMasterBrightMode_Up) || (compInfo.renderState.masterBrightnessMode == GPUMasterBrightMode_Down));
|
||||
}
|
||||
mutableInfo.needApplyMasterBrightness[this->_targetDisplayID] = (compInfo.renderState.masterBrightnessIntensity != 0) && ((compInfo.renderState.masterBrightnessMode == GPUMasterBrightMode_Up) || (compInfo.renderState.masterBrightnessMode == GPUMasterBrightMode_Down));
|
||||
|
||||
for (size_t line = 0; line < GPU_FRAMEBUFFER_NATIVE_HEIGHT; line++)
|
||||
{
|
||||
dispInfoMutable.masterBrightnessMode[this->_targetDisplayID][line] = compInfo.renderState.masterBrightnessMode;
|
||||
dispInfoMutable.masterBrightnessIntensity[this->_targetDisplayID][line] = compInfo.renderState.masterBrightnessIntensity;
|
||||
mutableInfo.masterBrightnessMode[this->_targetDisplayID][line] = compInfo.renderState.masterBrightnessMode;
|
||||
mutableInfo.masterBrightnessIntensity[this->_targetDisplayID][line] = compInfo.renderState.masterBrightnessIntensity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <NDSColorFormat OUTPUTFORMAT>
|
||||
void GPUEngineBase::ApplyMasterBrightness(const NDSDisplayInfo &displayInfo)
|
||||
{
|
||||
if (this->_willApplyMasterBrightnessPerScanline)
|
||||
{
|
||||
for (size_t line = 0; line < GPU_FRAMEBUFFER_NATIVE_HEIGHT; line++)
|
||||
{
|
||||
const GPUEngineCompositorInfo &compInfo = this->_currentCompositorInfo[line];
|
||||
void *dstColorLine = (!displayInfo.didPerformCustomRender[this->_targetDisplayID]) ? ((u8 *)displayInfo.nativeBuffer[this->_targetDisplayID] + (compInfo.line.blockOffsetNative * displayInfo.pixelBytes)) : ((u8 *)displayInfo.customBuffer[this->_targetDisplayID] + (compInfo.line.blockOffsetCustom * displayInfo.pixelBytes));
|
||||
const size_t pixCount = (!displayInfo.didPerformCustomRender[this->_targetDisplayID]) ? GPU_FRAMEBUFFER_NATIVE_WIDTH : compInfo.line.pixelCount;
|
||||
|
||||
this->ApplyMasterBrightness<OUTPUTFORMAT, false>(dstColorLine,
|
||||
pixCount,
|
||||
(GPUMasterBrightMode)displayInfo.masterBrightnessMode[this->_targetDisplayID][line],
|
||||
displayInfo.masterBrightnessIntensity[this->_targetDisplayID][line]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this->ApplyMasterBrightness<OUTPUTFORMAT, false>(displayInfo.renderedBuffer[this->_targetDisplayID],
|
||||
displayInfo.renderedWidth[this->_targetDisplayID] * displayInfo.renderedHeight[this->_targetDisplayID],
|
||||
(GPUMasterBrightMode)displayInfo.masterBrightnessMode[this->_targetDisplayID][0],
|
||||
displayInfo.masterBrightnessIntensity[this->_targetDisplayID][0]);
|
||||
}
|
||||
}
|
||||
|
||||
template <NDSColorFormat OUTPUTFORMAT, bool ISFULLINTENSITYHINT>
|
||||
void GPUEngineBase::ApplyMasterBrightness(void *dst, const size_t pixCount, const GPUMasterBrightMode mode, const u8 intensity)
|
||||
{
|
||||
|
@ -4951,43 +4948,36 @@ void GPUEngineBase::ResolveCustomRendering()
|
|||
this->renderedBuffer = this->customBuffer;
|
||||
}
|
||||
|
||||
void GPUEngineBase::ResolveRGB666ToRGB888()
|
||||
void GPUEngineBase::ResolveToCustomFramebuffer(NDSDisplayInfo &mutableInfo)
|
||||
{
|
||||
ColorspaceConvertBuffer6665To8888<false, false>((u32 *)this->renderedBuffer, (u32 *)this->renderedBuffer, this->renderedWidth * this->renderedHeight);
|
||||
}
|
||||
|
||||
void GPUEngineBase::ResolveToCustomFramebuffer()
|
||||
{
|
||||
const NDSDisplayInfo &dispInfo = GPU->GetDisplayInfo();
|
||||
|
||||
if (this->nativeLineOutputCount == 0)
|
||||
if (mutableInfo.didPerformCustomRender[this->_targetDisplayID])
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (dispInfo.isCustomSizeRequested)
|
||||
if (mutableInfo.isCustomSizeRequested)
|
||||
{
|
||||
if (dispInfo.pixelBytes == 2)
|
||||
if (mutableInfo.pixelBytes == 2)
|
||||
{
|
||||
for (size_t y = 0; y < GPU_FRAMEBUFFER_NATIVE_HEIGHT; y++)
|
||||
{
|
||||
this->_LineColorCopy<false, true, true, false, 2>(this->customBuffer, this->nativeBuffer, y);
|
||||
this->_LineColorCopy<false, true, true, false, 2>(mutableInfo.customBuffer[this->_targetDisplayID], mutableInfo.nativeBuffer[this->_targetDisplayID], y);
|
||||
}
|
||||
}
|
||||
else if (dispInfo.pixelBytes == 4)
|
||||
else if (mutableInfo.pixelBytes == 4)
|
||||
{
|
||||
for (size_t y = 0; y < GPU_FRAMEBUFFER_NATIVE_HEIGHT; y++)
|
||||
{
|
||||
this->_LineColorCopy<false, true, true, false, 4>(this->customBuffer, this->nativeBuffer, y);
|
||||
this->_LineColorCopy<false, true, true, false, 4>(mutableInfo.customBuffer[this->_targetDisplayID], mutableInfo.nativeBuffer[this->_targetDisplayID], y);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(this->customBuffer, this->nativeBuffer, GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * dispInfo.pixelBytes);
|
||||
memcpy(mutableInfo.customBuffer[this->_targetDisplayID], mutableInfo.nativeBuffer[this->_targetDisplayID], GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * mutableInfo.pixelBytes);
|
||||
}
|
||||
|
||||
GPU->SetDisplayDidCustomRender(this->_targetDisplayID, true);
|
||||
mutableInfo.didPerformCustomRender[this->_targetDisplayID] = true;
|
||||
}
|
||||
|
||||
void GPUEngineBase::RefreshAffineStartRegs()
|
||||
|
@ -6679,9 +6669,9 @@ void GPUEngineA::_LineLarge8bpp(GPUEngineCompositorInfo &compInfo)
|
|||
}
|
||||
}
|
||||
|
||||
void GPUEngineA::FramebufferPostprocess()
|
||||
void GPUEngineA::LastLineProcess()
|
||||
{
|
||||
this->GPUEngineBase::FramebufferPostprocess();
|
||||
this->GPUEngineBase::LastLineProcess();
|
||||
|
||||
this->_IORegisterMap->DISPCAPCNT.CaptureEnable = 0;
|
||||
DISP_FIFOreset();
|
||||
|
@ -6783,17 +6773,16 @@ GPUSubsystem::GPUSubsystem()
|
|||
_engineMain = GPUEngineA::Allocate();
|
||||
_engineSub = GPUEngineB::Allocate();
|
||||
|
||||
_displayMain = new NDSDisplay(NDSDisplayID_Main);
|
||||
_displayMain->SetEngine(_engineMain);
|
||||
_displayTouch = new NDSDisplay(NDSDisplayID_Touch);
|
||||
_displayTouch->SetEngine(_engineSub);
|
||||
_display[NDSDisplayID_Main] = new NDSDisplay(NDSDisplayID_Main);
|
||||
_display[NDSDisplayID_Main]->SetEngine(_engineMain);
|
||||
_display[NDSDisplayID_Touch] = new NDSDisplay(NDSDisplayID_Touch);
|
||||
_display[NDSDisplayID_Touch]->SetEngine(_engineSub);
|
||||
|
||||
_videoFrameCount = 0;
|
||||
_render3DFrameCount = 0;
|
||||
_frameNeedsFinish = false;
|
||||
_willFrameSkip = false;
|
||||
_willAutoApplyMasterBrightness = true;
|
||||
_willAutoConvertRGB666ToRGB888 = true;
|
||||
_willPostprocessDisplays = true;
|
||||
_willAutoResolveToCustomBuffer = true;
|
||||
|
||||
//TODO OSD
|
||||
|
@ -6806,7 +6795,6 @@ GPUSubsystem::GPUSubsystem()
|
|||
_displayInfo.isCustomSizeRequested = false;
|
||||
_displayInfo.customWidth = GPU_FRAMEBUFFER_NATIVE_WIDTH;
|
||||
_displayInfo.customHeight = GPU_FRAMEBUFFER_NATIVE_HEIGHT;
|
||||
_displayInfo.isMasterBrightnessAutoApplyRequested = true;
|
||||
|
||||
_customVRAM = NULL;
|
||||
_customVRAMBlank = NULL;
|
||||
|
@ -6854,8 +6842,8 @@ GPUSubsystem::~GPUSubsystem()
|
|||
free_aligned(_gpuDstToSrcSSSE3_u16_8e);
|
||||
_gpuDstToSrcSSSE3_u16_8e = NULL;
|
||||
|
||||
delete _displayMain;
|
||||
delete _displayTouch;
|
||||
delete _display[NDSDisplayID_Main];
|
||||
delete _display[NDSDisplayID_Touch];
|
||||
_engineMain->FinalizeAndDeallocate();
|
||||
_engineSub->FinalizeAndDeallocate();
|
||||
|
||||
|
@ -6912,8 +6900,8 @@ void GPUSubsystem::Reset()
|
|||
this->_displayInfo.renderedHeight[NDSDisplayID_Touch] = GPU_FRAMEBUFFER_NATIVE_HEIGHT;
|
||||
this->_displayInfo.renderedBuffer[NDSDisplayID_Touch] = this->_displayInfo.nativeBuffer[NDSDisplayID_Touch];
|
||||
|
||||
this->_displayMain->SetEngineByID(GPUEngineID_Main);
|
||||
this->_displayTouch->SetEngineByID(GPUEngineID_Sub);
|
||||
this->_display[NDSDisplayID_Main]->SetEngineByID(GPUEngineID_Main);
|
||||
this->_display[NDSDisplayID_Touch]->SetEngineByID(GPUEngineID_Sub);
|
||||
|
||||
gfx3d_reset();
|
||||
this->_engineMain->Reset();
|
||||
|
@ -6999,14 +6987,14 @@ void GPUSubsystem::UpdateRenderProperties()
|
|||
this->_engineSub->renderedWidth = GPU_FRAMEBUFFER_NATIVE_WIDTH;
|
||||
this->_engineSub->renderedHeight = GPU_FRAMEBUFFER_NATIVE_HEIGHT;
|
||||
|
||||
GPUEngineBase *mainEngine = this->_displayMain->GetEngine();
|
||||
GPUEngineBase *mainEngine = this->_display[NDSDisplayID_Main]->GetEngine();
|
||||
this->_displayInfo.nativeBuffer[NDSDisplayID_Main] = mainEngine->nativeBuffer;
|
||||
this->_displayInfo.customBuffer[NDSDisplayID_Main] = mainEngine->customBuffer;
|
||||
this->_displayInfo.renderedBuffer[NDSDisplayID_Main] = mainEngine->renderedBuffer;
|
||||
this->_displayInfo.renderedWidth[NDSDisplayID_Main] = mainEngine->renderedWidth;
|
||||
this->_displayInfo.renderedHeight[NDSDisplayID_Main] = mainEngine->renderedHeight;
|
||||
|
||||
GPUEngineBase *touchEngine = this->_displayTouch->GetEngine();
|
||||
GPUEngineBase *touchEngine = this->_display[NDSDisplayID_Touch]->GetEngine();
|
||||
this->_displayInfo.nativeBuffer[NDSDisplayID_Touch] = touchEngine->nativeBuffer;
|
||||
this->_displayInfo.customBuffer[NDSDisplayID_Touch] = touchEngine->customBuffer;
|
||||
this->_displayInfo.renderedBuffer[NDSDisplayID_Touch] = touchEngine->renderedBuffer;
|
||||
|
@ -7067,11 +7055,6 @@ u32 GPUSubsystem::GetFPSRender3D() const
|
|||
return this->_render3DFrameCount;
|
||||
}
|
||||
|
||||
void GPUSubsystem::SetDisplayDidCustomRender(NDSDisplayID displayID, bool theState)
|
||||
{
|
||||
this->_displayInfo.didPerformCustomRender[displayID] = theState;
|
||||
}
|
||||
|
||||
GPUEngineA* GPUSubsystem::GetEngineMain()
|
||||
{
|
||||
return this->_engineMain;
|
||||
|
@ -7084,12 +7067,12 @@ GPUEngineB* GPUSubsystem::GetEngineSub()
|
|||
|
||||
NDSDisplay* GPUSubsystem::GetDisplayMain()
|
||||
{
|
||||
return this->_displayMain;
|
||||
return this->_display[NDSDisplayID_Main];
|
||||
}
|
||||
|
||||
NDSDisplay* GPUSubsystem::GetDisplayTouch()
|
||||
{
|
||||
return this->_displayTouch;
|
||||
return this->_display[NDSDisplayID_Touch];
|
||||
}
|
||||
|
||||
size_t GPUSubsystem::GetCustomFramebufferWidth() const
|
||||
|
@ -7275,14 +7258,14 @@ void GPUSubsystem::_AllocateFramebuffers(NDSColorFormat outputFormat, size_t w,
|
|||
this->_engineMain->SetCustomFramebufferSize(w, h);
|
||||
this->_engineSub->SetCustomFramebufferSize(w, h);
|
||||
|
||||
GPUEngineBase *mainEngine = this->_displayMain->GetEngine();
|
||||
GPUEngineBase *mainEngine = this->_display[NDSDisplayID_Main]->GetEngine();
|
||||
this->_displayInfo.nativeBuffer[NDSDisplayID_Main] = mainEngine->nativeBuffer;
|
||||
this->_displayInfo.customBuffer[NDSDisplayID_Main] = mainEngine->customBuffer;
|
||||
this->_displayInfo.renderedBuffer[NDSDisplayID_Main] = mainEngine->renderedBuffer;
|
||||
this->_displayInfo.renderedWidth[NDSDisplayID_Main] = mainEngine->renderedWidth;
|
||||
this->_displayInfo.renderedHeight[NDSDisplayID_Main] = mainEngine->renderedHeight;
|
||||
|
||||
GPUEngineBase *touchEngine = this->_displayTouch->GetEngine();
|
||||
GPUEngineBase *touchEngine = this->_display[NDSDisplayID_Touch]->GetEngine();
|
||||
this->_displayInfo.nativeBuffer[NDSDisplayID_Touch] = touchEngine->nativeBuffer;
|
||||
this->_displayInfo.customBuffer[NDSDisplayID_Touch] = touchEngine->customBuffer;
|
||||
this->_displayInfo.renderedBuffer[NDSDisplayID_Touch] = touchEngine->renderedBuffer;
|
||||
|
@ -7344,25 +7327,75 @@ u16* GPUSubsystem::GetCustomVRAMAddressUsingMappedAddress(const u32 mappedAddr)
|
|||
return (this->GetEngineMain()->GetCustomVRAMBlockPtr(blockID) + (_gpuCaptureLineIndex[blockLine] * this->_displayInfo.customWidth) + _gpuDstPitchIndex[linePixel]);
|
||||
}
|
||||
|
||||
bool GPUSubsystem::GetWillAutoApplyMasterBrightness() const
|
||||
bool GPUSubsystem::GetWillPostprocessDisplays() const
|
||||
{
|
||||
return this->_willAutoApplyMasterBrightness;
|
||||
return this->_willPostprocessDisplays;
|
||||
}
|
||||
|
||||
void GPUSubsystem::SetWillAutoApplyMasterBrightness(const bool willAutoApply)
|
||||
void GPUSubsystem::SetWillPostprocessDisplays(const bool willPostprocess)
|
||||
{
|
||||
this->_willAutoApplyMasterBrightness = willAutoApply;
|
||||
this->_displayInfo.isMasterBrightnessAutoApplyRequested = willAutoApply;
|
||||
this->_willPostprocessDisplays = willPostprocess;
|
||||
}
|
||||
|
||||
bool GPUSubsystem::GetWillAutoConvertRGB666ToRGB888() const
|
||||
void GPUSubsystem::PostprocessDisplay(const NDSDisplayID displayID, NDSDisplayInfo &mutableInfo)
|
||||
{
|
||||
return this->_willAutoConvertRGB666ToRGB888;
|
||||
if (mutableInfo.isDisplayEnabled[displayID])
|
||||
{
|
||||
if (mutableInfo.colorFormat == NDSColorFormat_BGR666_Rev)
|
||||
{
|
||||
if (mutableInfo.needConvertColorFormat[displayID])
|
||||
{
|
||||
ColorspaceConvertBuffer6665To8888<false, false>((u32 *)mutableInfo.renderedBuffer[displayID], (u32 *)mutableInfo.renderedBuffer[displayID], mutableInfo.renderedWidth[displayID] * mutableInfo.renderedHeight[displayID]);
|
||||
}
|
||||
|
||||
if (mutableInfo.needApplyMasterBrightness[displayID])
|
||||
{
|
||||
this->_display[displayID]->GetEngine()->ApplyMasterBrightness<NDSColorFormat_BGR888_Rev>(mutableInfo);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mutableInfo.needApplyMasterBrightness[displayID])
|
||||
{
|
||||
switch (mutableInfo.colorFormat)
|
||||
{
|
||||
case NDSColorFormat_BGR555_Rev:
|
||||
this->_display[displayID]->GetEngine()->ApplyMasterBrightness<NDSColorFormat_BGR555_Rev>(mutableInfo);
|
||||
break;
|
||||
|
||||
case NDSColorFormat_BGR666_Rev:
|
||||
this->_display[displayID]->GetEngine()->ApplyMasterBrightness<NDSColorFormat_BGR666_Rev>(mutableInfo);
|
||||
break;
|
||||
|
||||
case NDSColorFormat_BGR888_Rev:
|
||||
this->_display[displayID]->GetEngine()->ApplyMasterBrightness<NDSColorFormat_BGR888_Rev>(mutableInfo);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mutableInfo.colorFormat == NDSColorFormat_BGR555_Rev)
|
||||
{
|
||||
memset(mutableInfo.renderedBuffer[displayID], 0, mutableInfo.renderedWidth[displayID] * mutableInfo.renderedHeight[displayID] * sizeof(u16));
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(mutableInfo.renderedBuffer[displayID], 0, mutableInfo.renderedWidth[displayID] * mutableInfo.renderedHeight[displayID] * sizeof(u32));
|
||||
}
|
||||
}
|
||||
|
||||
mutableInfo.needConvertColorFormat[displayID] = false;
|
||||
mutableInfo.needApplyMasterBrightness[displayID] = false;
|
||||
}
|
||||
|
||||
void GPUSubsystem::SetWillAutoConvertRGB666ToRGB888(const bool willAutoConvert)
|
||||
void GPUSubsystem::ResolveDisplayToCustomFramebuffer(const NDSDisplayID displayID, NDSDisplayInfo &mutableInfo)
|
||||
{
|
||||
this->_willAutoConvertRGB666ToRGB888 = willAutoConvert;
|
||||
this->_display[displayID]->GetEngine()->ResolveToCustomFramebuffer(mutableInfo);
|
||||
}
|
||||
|
||||
bool GPUSubsystem::GetWillAutoResolveToCustomBuffer() const
|
||||
|
@ -7450,8 +7483,8 @@ void GPUSubsystem::RenderLine(const size_t l)
|
|||
|
||||
if (l == 191)
|
||||
{
|
||||
this->_engineMain->FramebufferPostprocess();
|
||||
this->_engineSub->FramebufferPostprocess();
|
||||
this->_engineMain->LastLineProcess();
|
||||
this->_engineSub->LastLineProcess();
|
||||
|
||||
this->_UpdateFPSRender3D();
|
||||
|
||||
|
@ -7463,55 +7496,35 @@ void GPUSubsystem::RenderLine(const size_t l)
|
|||
this->_engineSub->ResolveCustomRendering<OUTPUTFORMAT>();
|
||||
}
|
||||
|
||||
this->_displayInfo.didPerformCustomRender[NDSDisplayID_Main] = (this->_displayMain->GetEngine()->nativeLineOutputCount < GPU_FRAMEBUFFER_NATIVE_HEIGHT);
|
||||
this->_displayInfo.renderedBuffer[NDSDisplayID_Main] = this->_displayMain->GetEngine()->renderedBuffer;
|
||||
this->_displayInfo.renderedWidth[NDSDisplayID_Main] = this->_displayMain->GetEngine()->renderedWidth;
|
||||
this->_displayInfo.renderedHeight[NDSDisplayID_Main] = this->_displayMain->GetEngine()->renderedHeight;
|
||||
this->_displayInfo.didPerformCustomRender[NDSDisplayID_Main] = (this->_display[NDSDisplayID_Main]->GetEngine()->nativeLineOutputCount < GPU_FRAMEBUFFER_NATIVE_HEIGHT);
|
||||
this->_displayInfo.renderedBuffer[NDSDisplayID_Main] = this->_display[NDSDisplayID_Main]->GetEngine()->renderedBuffer;
|
||||
this->_displayInfo.renderedWidth[NDSDisplayID_Main] = this->_display[NDSDisplayID_Main]->GetEngine()->renderedWidth;
|
||||
this->_displayInfo.renderedHeight[NDSDisplayID_Main] = this->_display[NDSDisplayID_Main]->GetEngine()->renderedHeight;
|
||||
|
||||
this->_displayInfo.didPerformCustomRender[NDSDisplayID_Touch] = (this->_displayTouch->GetEngine()->nativeLineOutputCount < GPU_FRAMEBUFFER_NATIVE_HEIGHT);
|
||||
this->_displayInfo.renderedBuffer[NDSDisplayID_Touch] = this->_displayTouch->GetEngine()->renderedBuffer;
|
||||
this->_displayInfo.renderedWidth[NDSDisplayID_Touch] = this->_displayTouch->GetEngine()->renderedWidth;
|
||||
this->_displayInfo.renderedHeight[NDSDisplayID_Touch] = this->_displayTouch->GetEngine()->renderedHeight;
|
||||
this->_displayInfo.didPerformCustomRender[NDSDisplayID_Touch] = (this->_display[NDSDisplayID_Touch]->GetEngine()->nativeLineOutputCount < GPU_FRAMEBUFFER_NATIVE_HEIGHT);
|
||||
this->_displayInfo.renderedBuffer[NDSDisplayID_Touch] = this->_display[NDSDisplayID_Touch]->GetEngine()->renderedBuffer;
|
||||
this->_displayInfo.renderedWidth[NDSDisplayID_Touch] = this->_display[NDSDisplayID_Touch]->GetEngine()->renderedWidth;
|
||||
this->_displayInfo.renderedHeight[NDSDisplayID_Touch] = this->_display[NDSDisplayID_Touch]->GetEngine()->renderedHeight;
|
||||
|
||||
this->_displayInfo.isDisplayEnabled[NDSDisplayID_Main] = CommonSettings.showGpu.main;
|
||||
this->_displayInfo.isDisplayEnabled[NDSDisplayID_Touch] = CommonSettings.showGpu.sub;
|
||||
this->_displayInfo.needApplyMasterBrightness[NDSDisplayID_Main] = !this->_displayInfo.isMasterBrightnessAutoApplyRequested;
|
||||
this->_displayInfo.needApplyMasterBrightness[NDSDisplayID_Touch] = !this->_displayInfo.isMasterBrightnessAutoApplyRequested;
|
||||
this->_displayInfo.isDisplayEnabled[NDSDisplayID_Main] = CommonSettings.showGpu.screens[this->_display[NDSDisplayID_Main]->GetEngineID()];
|
||||
this->_displayInfo.isDisplayEnabled[NDSDisplayID_Touch] = CommonSettings.showGpu.screens[this->_display[NDSDisplayID_Touch]->GetEngineID()];
|
||||
|
||||
if (CommonSettings.showGpu.main)
|
||||
{
|
||||
this->_engineMain->ApplyMasterBrightness<OUTPUTFORMAT>();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this->_willAutoApplyMasterBrightness)
|
||||
{
|
||||
memset(this->_engineMain->renderedBuffer, 0, this->_engineMain->renderedWidth * this->_engineMain->renderedHeight * this->_displayInfo.pixelBytes);
|
||||
}
|
||||
}
|
||||
this->_displayInfo.needConvertColorFormat[NDSDisplayID_Main] = (OUTPUTFORMAT == NDSColorFormat_BGR666_Rev);
|
||||
this->_displayInfo.needConvertColorFormat[NDSDisplayID_Touch] = (OUTPUTFORMAT == NDSColorFormat_BGR666_Rev);
|
||||
|
||||
if (CommonSettings.showGpu.sub)
|
||||
{
|
||||
this->_engineSub->ApplyMasterBrightness<OUTPUTFORMAT>();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this->_willAutoApplyMasterBrightness)
|
||||
{
|
||||
memset(this->_engineSub->renderedBuffer, 0, this->_engineSub->renderedWidth * this->_engineSub->renderedHeight * this->_displayInfo.pixelBytes);
|
||||
}
|
||||
}
|
||||
this->_engineMain->UpdateMasterBrightnessDisplayInfo(this->_displayInfo);
|
||||
this->_engineSub->UpdateMasterBrightnessDisplayInfo(this->_displayInfo);
|
||||
|
||||
if ( (OUTPUTFORMAT == NDSColorFormat_BGR666_Rev) && this->_willAutoConvertRGB666ToRGB888 )
|
||||
if (this->_willPostprocessDisplays)
|
||||
{
|
||||
this->_engineMain->ResolveRGB666ToRGB888();
|
||||
this->_engineSub->ResolveRGB666ToRGB888();
|
||||
this->PostprocessDisplay(NDSDisplayID_Main, this->_displayInfo);
|
||||
this->PostprocessDisplay(NDSDisplayID_Touch, this->_displayInfo);
|
||||
}
|
||||
|
||||
if (this->_willAutoResolveToCustomBuffer)
|
||||
{
|
||||
this->_engineMain->ResolveToCustomFramebuffer();
|
||||
this->_engineSub->ResolveToCustomFramebuffer();
|
||||
this->ResolveDisplayToCustomFramebuffer(NDSDisplayID_Main, this->_displayInfo);
|
||||
this->ResolveDisplayToCustomFramebuffer(NDSDisplayID_Touch, this->_displayInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1073,28 +1073,19 @@ typedef struct
|
|||
// Changed by calling GPUSubsystem::SetColorFormat() or GPUSubsystem::SetFramebufferSize().
|
||||
void *masterFramebufferHead; // Pointer to the head of the master framebuffer memory block that encompasses all buffers.
|
||||
|
||||
// Changed by calling GPUSubsystem::SetWillAutoApplyMasterBrightness().
|
||||
bool isMasterBrightnessAutoApplyRequested; // Reports the result of GPUSubsystem::GetWillAutoApplyMasterBrightness().
|
||||
// true - The emulator itself will apply the master brightness. This is the default option.
|
||||
// false - The output framebuffer will not have master brightness applied. Clients will need to
|
||||
// apply the master brightness themselves in a post-processing pass. Clients should use
|
||||
// the needApplyMasterBrightness, masterBrightnessMode, masterBrightnessIntensity and
|
||||
// isDisplayEnabled properties to determine how to apply the master brightness on their
|
||||
// end.
|
||||
|
||||
// Changed by calling GPUEngineBase::SetEnableState().
|
||||
bool isDisplayEnabled[2]; // Reports that a particular display has been enabled or disabled by the user.
|
||||
|
||||
|
||||
|
||||
// Frame information. These fields will change per frame, depending on how each display was rendered.
|
||||
// Frame render state information. These fields will change per frame, depending on how each display was rendered.
|
||||
u8 bufferIndex; // Index of this frame's buffer set.
|
||||
|
||||
void *masterNativeBuffer; // Pointer to the head of the master native buffer.
|
||||
void *masterCustomBuffer; // Pointer to the head of the master custom buffer.
|
||||
// If GPUSubsystem::GetWillAutoResolveToCustomBuffer() would return true, or if
|
||||
// GPUEngineBase::ResolveToCustomFramebuffer() is called, then this buffer is used as the target
|
||||
// buffer for resolving any native-sized renders.
|
||||
// GPUSubsystem::ResolveDisplayToCustomFramebuffer() is called, then this buffer is used as the
|
||||
// target buffer for resolving any native-sized renders.
|
||||
|
||||
void *nativeBuffer[2]; // Pointer to the display's native size framebuffer.
|
||||
void *customBuffer[2]; // Pointer to the display's custom size framebuffer.
|
||||
|
@ -1107,11 +1098,15 @@ typedef struct
|
|||
// true - The display performed a custom-sized render.
|
||||
// false - The display performed a native-sized render.
|
||||
|
||||
bool needApplyMasterBrightness[2]; // Reports if a display still needs to apply the master brightness. This will be true if the
|
||||
// isMasterBrightnessAutoApplyRequested flag is false and if the NDS has a master brightness
|
||||
// intensity of non-zero for at least one line.
|
||||
u8 masterBrightnessMode[2][GPU_FRAMEBUFFER_NATIVE_HEIGHT]; // The master brightness mode of each display line.
|
||||
u8 masterBrightnessIntensity[2][GPU_FRAMEBUFFER_NATIVE_HEIGHT]; // The master brightness intensity of each display line.
|
||||
|
||||
|
||||
|
||||
// Postprocessing information. These fields report the status of each postprocessing step.
|
||||
// Typically, these fields should be modified whenever GPUSubsystem::PostprocessDisplay() is called.
|
||||
bool needConvertColorFormat[2]; // Reports if the display still needs to convert its color format from RGB666 to RGB888.
|
||||
bool needApplyMasterBrightness[2]; // Reports if the display still needs to apply the master brightness.
|
||||
} NDSDisplayInfo;
|
||||
|
||||
#define VRAM_NO_3D_USAGE 0xFF
|
||||
|
@ -1453,7 +1448,7 @@ public:
|
|||
void ParseAllRegisters();
|
||||
|
||||
void UpdatePropertiesWithoutRender(const u16 l);
|
||||
void FramebufferPostprocess();
|
||||
void LastLineProcess();
|
||||
|
||||
u8 vramBlockOBJIndex;
|
||||
|
||||
|
@ -1502,7 +1497,8 @@ public:
|
|||
bool WillApplyMasterBrightnessPerScanline() const;
|
||||
void SetWillApplyMasterBrightnessPerScanline(bool willApply);
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT> void ApplyMasterBrightness();
|
||||
void UpdateMasterBrightnessDisplayInfo(NDSDisplayInfo &mutableInfo);
|
||||
template<NDSColorFormat OUTPUTFORMAT> void ApplyMasterBrightness(const NDSDisplayInfo &displayInfo);
|
||||
template<NDSColorFormat OUTPUTFORMAT, bool ISFULLINTENSITYHINT> void ApplyMasterBrightness(void *dst, const size_t pixCount, const GPUMasterBrightMode mode, const u8 intensity);
|
||||
|
||||
const BGLayerInfo& GetBGLayerInfoByID(const GPULayerID layerID);
|
||||
|
@ -1519,8 +1515,7 @@ public:
|
|||
|
||||
virtual void SetCustomFramebufferSize(size_t w, size_t h);
|
||||
template<NDSColorFormat OUTPUTFORMAT> void ResolveCustomRendering();
|
||||
void ResolveRGB666ToRGB888();
|
||||
void ResolveToCustomFramebuffer();
|
||||
void ResolveToCustomFramebuffer(NDSDisplayInfo &mutableInfo);
|
||||
|
||||
void REG_DISPx_pack_test();
|
||||
};
|
||||
|
@ -1585,7 +1580,7 @@ public:
|
|||
bool WillDisplayCapture(const size_t l);
|
||||
bool VerifyVRAMLineDidChange(const size_t blockID, const size_t l);
|
||||
|
||||
void FramebufferPostprocess();
|
||||
void LastLineProcess();
|
||||
|
||||
virtual void Reset();
|
||||
|
||||
|
@ -1655,15 +1650,13 @@ private:
|
|||
|
||||
GPUEngineA *_engineMain;
|
||||
GPUEngineB *_engineSub;
|
||||
NDSDisplay *_displayMain;
|
||||
NDSDisplay *_displayTouch;
|
||||
NDSDisplay *_display[2];
|
||||
|
||||
u32 _videoFrameCount; // Internal variable that increments when a video frame is completed. Resets every 60 video frames.
|
||||
u32 _render3DFrameCount; // The current 3D rendering frame count, saved to this variable once every 60 video frames.
|
||||
bool _frameNeedsFinish;
|
||||
bool _willFrameSkip;
|
||||
bool _willAutoApplyMasterBrightness;
|
||||
bool _willAutoConvertRGB666ToRGB888;
|
||||
bool _willPostprocessDisplays;
|
||||
bool _willAutoResolveToCustomBuffer;
|
||||
u16 *_customVRAM;
|
||||
u16 *_customVRAMBlank;
|
||||
|
@ -1689,8 +1682,6 @@ public:
|
|||
const NDSDisplayInfo& GetDisplayInfo(); // Frontends need to call this whenever they need to read the video buffers from the emulator core
|
||||
u32 GetFPSRender3D() const;
|
||||
|
||||
void SetDisplayDidCustomRender(NDSDisplayID displayID, bool theState);
|
||||
|
||||
GPUEngineA* GetEngineMain();
|
||||
GPUEngineB* GetEngineSub();
|
||||
NDSDisplay* GetDisplayMain();
|
||||
|
@ -1709,25 +1700,22 @@ public:
|
|||
void SetWillFrameSkip(const bool willFrameSkip);
|
||||
void UpdateRenderProperties();
|
||||
|
||||
// By default, the output framebuffer will have the master brightness applied before
|
||||
// the DidFrameEnd event. The master brightness is applied using the CPU.
|
||||
// By default, the displays will automatically perform certain postprocessing steps on the
|
||||
// CPU before the DidFrameEnd event.
|
||||
//
|
||||
// To turn off this behavior, call SetWillAutoApplyMasterBrightness() and pass a value
|
||||
// of "false". This can be useful if the client wants to apply the master brightness
|
||||
// itself, for example, if a client applies it on the GPU.
|
||||
bool GetWillAutoApplyMasterBrightness() const;
|
||||
void SetWillAutoApplyMasterBrightness(const bool willAutoApply);
|
||||
|
||||
// By default, if the output framebuffer is in RGB666 format, then the framebuffers will
|
||||
// automatically be converted to the much more common RGB888 format. This conversion is
|
||||
// performed on the CPU.
|
||||
// To turn off this behavior, call SetWillPostprocessDisplays() and pass a value of "false".
|
||||
// This can be useful if the client wants to perform these postprocessing steps itself, for
|
||||
// example, if a client performs them on another thread or on the GPU.
|
||||
//
|
||||
// To turn off this behavior, call SetWillAutoConvertRGB666ToRGB888() and pass a value
|
||||
// of "false". This can be useful if the client wants to do its own post-processing
|
||||
// while the color format is still RGB666, or if the client wants to do its own custom
|
||||
// conversion (such as converting the framebuffer later on the GPU).
|
||||
bool GetWillAutoConvertRGB666ToRGB888() const;
|
||||
void SetWillAutoConvertRGB666ToRGB888(const bool willAutoConvert);
|
||||
// If automatic postprocessing is turned off, clients can still manually perform the
|
||||
// postprocessing steps on the CPU by calling PostprocessDisplay().
|
||||
//
|
||||
// The postprocessing steps that are performed are:
|
||||
// - Converting an RGB666 formatted framebuffer to RGB888 format.
|
||||
// - Applying the master brightness.
|
||||
bool GetWillPostprocessDisplays() const;
|
||||
void SetWillPostprocessDisplays(const bool willPostprocess);
|
||||
void PostprocessDisplay(const NDSDisplayID displayID, NDSDisplayInfo &mutableInfo);
|
||||
|
||||
// Normally, the GPUs will automatically resolve their native buffers to the master
|
||||
// custom framebuffer at the end of V-blank so that all rendered graphics are contained
|
||||
|
@ -1736,14 +1724,14 @@ public:
|
|||
// Certain functions, such as taking screenshots, as well as many frontends running
|
||||
// the NDS video displays, require that they read from only a single buffer.
|
||||
//
|
||||
// However, if SetWillAutoResolveToCustomBuffer() is passed "false", then the
|
||||
// frontend becomes responsible for calling GetDisplayInfo() and reading the native
|
||||
// and custom buffers properly for each display. If a single buffer is still needed
|
||||
// for certain cases, then the frontend must manually call
|
||||
// GPUEngineBase::ResolveToCustomFramebuffer() for each engine before reading the
|
||||
// master custom framebuffer.
|
||||
// However, if SetWillAutoResolveToCustomBuffer() is passed "false", then the frontend
|
||||
// becomes responsible for calling GetDisplayInfo() and reading the native and custom buffers
|
||||
// properly for each display. If a single buffer is still needed for certain cases, then the
|
||||
// frontend must manually call ResolveDisplayToCustomFramebuffer() for each display before
|
||||
// reading the master custom framebuffer.
|
||||
bool GetWillAutoResolveToCustomBuffer() const;
|
||||
void SetWillAutoResolveToCustomBuffer(const bool willAutoResolve);
|
||||
void ResolveDisplayToCustomFramebuffer(const NDSDisplayID displayID, NDSDisplayInfo &mutableInfo);
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT> void RenderLine(const size_t l);
|
||||
void ClearWithColor(const u16 colorBGRA5551);
|
||||
|
|
|
@ -4709,7 +4709,7 @@ bool OGLShaderProgram::LinkOGL()
|
|||
OGLClientFetchObject::OGLClientFetchObject()
|
||||
{
|
||||
_contextInfo = NULL;
|
||||
_useCPUFilterPipeline = true;
|
||||
_useDirectToCPUFilterPipeline = true;
|
||||
_fetchColorFormatOGL = GL_UNSIGNED_SHORT_1_5_5_5_REV;
|
||||
|
||||
pthread_rwlock_init(&_srcCloneRWLock[NDSDisplayID_Main][0], NULL);
|
||||
|
@ -4923,7 +4923,7 @@ void OGLClientFetchObject::SetFetchBuffers(const NDSDisplayInfo ¤tDisplayI
|
|||
|
||||
void OGLClientFetchObject::_FetchNativeDisplayByID(const NDSDisplayID displayID, const u8 bufferIndex)
|
||||
{
|
||||
if (this->_useCPUFilterPipeline)
|
||||
if (this->_useDirectToCPUFilterPipeline)
|
||||
{
|
||||
pthread_rwlock_wrlock(&this->_srcCloneRWLock[displayID][bufferIndex]);
|
||||
|
||||
|
|
|
@ -343,7 +343,7 @@ protected:
|
|||
GLuint _texHQ3xLUT;
|
||||
GLuint _texHQ4xLUT;
|
||||
|
||||
bool _useCPUFilterPipeline;
|
||||
bool _useDirectToCPUFilterPipeline;
|
||||
uint32_t *_srcNativeCloneMaster;
|
||||
uint32_t *_srcNativeClone[2][2];
|
||||
pthread_rwlock_t _srcCloneRWLock[2][2];
|
||||
|
|
|
@ -38,17 +38,17 @@ class GPUEventHandlerOSX;
|
|||
pthread_rwlock_t *_rwlockFramebuffer[2];
|
||||
pthread_mutex_t *_mutexOutputList;
|
||||
NSMutableArray *_cdsOutputList;
|
||||
volatile int32_t numberViewsUsingCPUFiltering;
|
||||
volatile int32_t numberViewsUsingDirectToCPUFiltering;
|
||||
}
|
||||
|
||||
@property (assign, nonatomic) GPUClientFetchObject *GPUFetchObject;
|
||||
@property (readonly, nonatomic) int32_t numberViewsUsingCPUFiltering;
|
||||
@property (readonly, nonatomic) int32_t numberViewsUsingDirectToCPUFiltering;
|
||||
|
||||
- (const NDSDisplayInfo &) fetchDisplayInfoForIndex:(const u8)bufferIndex;
|
||||
- (pthread_rwlock_t *) rwlockFramebufferAtIndex:(const u8)bufferIndex;
|
||||
- (void) setOutputList:(NSMutableArray *)theOutputList mutex:(pthread_mutex_t *)theMutex;
|
||||
- (void) incrementViewsUsingCPUFiltering;
|
||||
- (void) decrementViewsUsingCPUFiltering;
|
||||
- (void) incrementViewsUsingDirectToCPUFiltering;
|
||||
- (void) decrementViewsUsingDirectToCPUFiltering;
|
||||
- (void) handleFetchFromBufferIndexAndPushVideo:(NSData *)indexData;
|
||||
- (void) pushVideoDataToAllDisplayViews;
|
||||
- (void) finishAllDisplayViewsAtIndex:(const u8)bufferIndex;
|
||||
|
|
|
@ -159,11 +159,16 @@ public:
|
|||
if (IsOSXVersionSupported(10, 11, 0) && [[NSUserDefaults standardUserDefaults] boolForKey:@"General_DisplayViewsPreferMetal"])
|
||||
{
|
||||
fetchObject = new MacMetalFetchObject;
|
||||
|
||||
if (fetchObject->GetClientData() == nil)
|
||||
{
|
||||
delete fetchObject;
|
||||
fetchObject = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
GPU->SetWillPostprocessDisplays(false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -860,7 +865,7 @@ public:
|
|||
@implementation MacClientSharedObject
|
||||
|
||||
@synthesize GPUFetchObject;
|
||||
@synthesize numberViewsUsingCPUFiltering;
|
||||
@synthesize numberViewsUsingDirectToCPUFiltering;
|
||||
|
||||
- (id)init
|
||||
{
|
||||
|
@ -879,7 +884,7 @@ public:
|
|||
GPUFetchObject = nil;
|
||||
_mutexOutputList = NULL;
|
||||
_cdsOutputList = nil;
|
||||
numberViewsUsingCPUFiltering = 0;
|
||||
numberViewsUsingDirectToCPUFiltering = 0;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
@ -962,14 +967,14 @@ public:
|
|||
_mutexOutputList = theMutex;
|
||||
}
|
||||
|
||||
- (void) incrementViewsUsingCPUFiltering
|
||||
- (void) incrementViewsUsingDirectToCPUFiltering
|
||||
{
|
||||
OSAtomicIncrement32(&numberViewsUsingCPUFiltering);
|
||||
OSAtomicIncrement32(&numberViewsUsingDirectToCPUFiltering);
|
||||
}
|
||||
|
||||
- (void) decrementViewsUsingCPUFiltering
|
||||
- (void) decrementViewsUsingDirectToCPUFiltering
|
||||
{
|
||||
OSAtomicDecrement32(&numberViewsUsingCPUFiltering);
|
||||
OSAtomicDecrement32(&numberViewsUsingDirectToCPUFiltering);
|
||||
}
|
||||
|
||||
- (void) pushVideoDataToAllDisplayViews
|
||||
|
|
|
@ -678,9 +678,11 @@
|
|||
|
||||
- (NSBitmapImageRep *) bitmapImageRep
|
||||
{
|
||||
const NDSDisplayInfo &dispInfo = GPU->GetDisplayInfo();
|
||||
NSUInteger w = (NSUInteger)dispInfo.customWidth;
|
||||
NSUInteger h = (_cdv->GetMode() == ClientDisplayMode_Dual) ? (NSUInteger)(dispInfo.customHeight * 2) : (NSUInteger)dispInfo.customHeight;
|
||||
GPUClientFetchObject &fetchObjMutable = (GPUClientFetchObject &)_cdv->GetFetchObject();
|
||||
NDSDisplayInfo &displayInfoMutable = (NDSDisplayInfo &)fetchObjMutable.GetFetchDisplayInfoForBufferIndex(fetchObjMutable.GetLastFetchIndex());
|
||||
|
||||
NSUInteger w = (NSUInteger)displayInfoMutable.customWidth;
|
||||
NSUInteger h = (_cdv->GetMode() == ClientDisplayMode_Dual) ? (NSUInteger)(displayInfoMutable.customHeight * 2) : (NSUInteger)displayInfoMutable.customHeight;
|
||||
|
||||
NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
|
||||
pixelsWide:w
|
||||
|
@ -698,19 +700,21 @@
|
|||
return imageRep;
|
||||
}
|
||||
|
||||
void *displayBuffer = dispInfo.masterCustomBuffer;
|
||||
void *displayBuffer = displayInfoMutable.masterCustomBuffer;
|
||||
uint32_t *bitmapData = (uint32_t *)[imageRep bitmapData];
|
||||
|
||||
pthread_rwlock_rdlock(self.rwlockProducer);
|
||||
pthread_rwlock_wrlock(self.rwlockProducer);
|
||||
|
||||
GPU->GetEngineMain()->ResolveToCustomFramebuffer();
|
||||
GPU->GetEngineSub()->ResolveToCustomFramebuffer();
|
||||
GPU->PostprocessDisplay(NDSDisplayID_Main, displayInfoMutable);
|
||||
GPU->PostprocessDisplay(NDSDisplayID_Touch, displayInfoMutable);
|
||||
GPU->ResolveDisplayToCustomFramebuffer(NDSDisplayID_Main, displayInfoMutable);
|
||||
GPU->ResolveDisplayToCustomFramebuffer(NDSDisplayID_Touch, displayInfoMutable);
|
||||
|
||||
if (dispInfo.pixelBytes == 2)
|
||||
if (displayInfoMutable.pixelBytes == 2)
|
||||
{
|
||||
ColorspaceConvertBuffer555To8888Opaque<false, true>((u16 *)displayBuffer, bitmapData, (w * h));
|
||||
}
|
||||
else if (dispInfo.pixelBytes == 4)
|
||||
else if (displayInfoMutable.pixelBytes == 4)
|
||||
{
|
||||
memcpy(bitmapData, displayBuffer, w * h * sizeof(uint32_t));
|
||||
}
|
||||
|
|
|
@ -1751,9 +1751,9 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
|
|||
|
||||
- (void) setVideoFiltersPreferGPU:(BOOL)theState
|
||||
{
|
||||
const BOOL oldState = (![[self cdsVideoOutput] willFilterOnGPU] && ([[self cdsVideoOutput] pixelScaler] != VideoFilterTypeID_None));
|
||||
const BOOL oldState = ( ![[self cdsVideoOutput] willFilterOnGPU] && ![[self cdsVideoOutput] sourceDeposterize] && ([[self cdsVideoOutput] pixelScaler] != VideoFilterTypeID_None) );
|
||||
[[self cdsVideoOutput] setVideoFiltersPreferGPU:theState];
|
||||
const BOOL newState = (![[self cdsVideoOutput] willFilterOnGPU] && ([[self cdsVideoOutput] pixelScaler] != VideoFilterTypeID_None));
|
||||
const BOOL newState = ( ![[self cdsVideoOutput] willFilterOnGPU] && ![[self cdsVideoOutput] sourceDeposterize] && ([[self cdsVideoOutput] pixelScaler] != VideoFilterTypeID_None) );
|
||||
|
||||
if (oldState != newState)
|
||||
{
|
||||
|
@ -1764,11 +1764,11 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
|
|||
|
||||
if (newState)
|
||||
{
|
||||
[macSharedData incrementViewsUsingCPUFiltering];
|
||||
[macSharedData incrementViewsUsingDirectToCPUFiltering];
|
||||
}
|
||||
else
|
||||
{
|
||||
[macSharedData decrementViewsUsingCPUFiltering];
|
||||
[macSharedData decrementViewsUsingDirectToCPUFiltering];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1780,7 +1780,26 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
|
|||
|
||||
- (void) setSourceDeposterize:(BOOL)theState
|
||||
{
|
||||
const BOOL oldState = ( ![[self cdsVideoOutput] willFilterOnGPU] && ![[self cdsVideoOutput] sourceDeposterize] && ([[self cdsVideoOutput] pixelScaler] != VideoFilterTypeID_None) );
|
||||
[[self cdsVideoOutput] setSourceDeposterize:theState];
|
||||
const BOOL newState = ( ![[self cdsVideoOutput] willFilterOnGPU] && ![[self cdsVideoOutput] sourceDeposterize] && ([[self cdsVideoOutput] pixelScaler] != VideoFilterTypeID_None) );
|
||||
|
||||
if (oldState != newState)
|
||||
{
|
||||
DisplayWindowController *windowController = (DisplayWindowController *)[[self window] delegate];
|
||||
CocoaDSCore *cdsCore = (CocoaDSCore *)[[[windowController emuControl] cdsCoreController] content];
|
||||
CocoaDSGPU *cdsGPU = [cdsCore cdsGPU];
|
||||
MacClientSharedObject *macSharedData = [cdsGPU sharedData];
|
||||
|
||||
if (newState)
|
||||
{
|
||||
[macSharedData incrementViewsUsingDirectToCPUFiltering];
|
||||
}
|
||||
else
|
||||
{
|
||||
[macSharedData decrementViewsUsingDirectToCPUFiltering];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL) sourceDeposterize
|
||||
|
@ -1800,9 +1819,9 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
|
|||
|
||||
- (void) setPixelScaler:(NSInteger)filterID
|
||||
{
|
||||
const BOOL oldState = (![[self cdsVideoOutput] willFilterOnGPU] && ([[self cdsVideoOutput] pixelScaler] != VideoFilterTypeID_None));
|
||||
const BOOL oldState = ( ![[self cdsVideoOutput] willFilterOnGPU] && ![[self cdsVideoOutput] sourceDeposterize] && ([[self cdsVideoOutput] pixelScaler] != VideoFilterTypeID_None) );
|
||||
[[self cdsVideoOutput] setPixelScaler:filterID];
|
||||
const BOOL newState = (![[self cdsVideoOutput] willFilterOnGPU] && ([[self cdsVideoOutput] pixelScaler] != VideoFilterTypeID_None));
|
||||
const BOOL newState = ( ![[self cdsVideoOutput] willFilterOnGPU] && ![[self cdsVideoOutput] sourceDeposterize] && ([[self cdsVideoOutput] pixelScaler] != VideoFilterTypeID_None) );
|
||||
|
||||
if (oldState != newState)
|
||||
{
|
||||
|
@ -1813,11 +1832,11 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
|
|||
|
||||
if (newState)
|
||||
{
|
||||
[macSharedData incrementViewsUsingCPUFiltering];
|
||||
[macSharedData incrementViewsUsingDirectToCPUFiltering];
|
||||
}
|
||||
else
|
||||
{
|
||||
[macSharedData decrementViewsUsingCPUFiltering];
|
||||
[macSharedData decrementViewsUsingDirectToCPUFiltering];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,7 +48,10 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties;
|
|||
id<MTLCommandQueue> commandQueue;
|
||||
id<MTLLibrary> defaultLibrary;
|
||||
|
||||
id<MTLComputePipelineState> load16To32Pipeline;
|
||||
id<MTLComputePipelineState> _fetch555Pipeline;
|
||||
id<MTLComputePipelineState> _fetch555ConvertOnlyPipeline;
|
||||
id<MTLComputePipelineState> _fetch666Pipeline;
|
||||
id<MTLComputePipelineState> _fetch888Pipeline;
|
||||
id<MTLComputePipelineState> deposterizePipeline;
|
||||
id<MTLRenderPipelineState> hudPipeline;
|
||||
|
||||
|
@ -61,6 +64,9 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties;
|
|||
id<MTLBuffer> _bufDisplayFetchNative[2][2];
|
||||
id<MTLBuffer> _bufDisplayFetchCustom[2][2];
|
||||
|
||||
id<MTLBuffer> _bufMasterBrightMode[2];
|
||||
id<MTLBuffer> _bufMasterBrightIntensity[2];
|
||||
|
||||
id<MTLTexture> texDisplayFetch16NativeMain;
|
||||
id<MTLTexture> texDisplayFetch16NativeTouch;
|
||||
id<MTLTexture> texDisplayFetch32NativeMain;
|
||||
|
@ -70,15 +76,23 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties;
|
|||
id<MTLTexture> texDisplayFetch32CustomMain;
|
||||
id<MTLTexture> texDisplayFetch32CustomTouch;
|
||||
|
||||
id<MTLTexture> texDisplayPostprocessNativeMain;
|
||||
id<MTLTexture> texDisplayPostprocessCustomMain;
|
||||
id<MTLTexture> texDisplayPostprocessNativeTouch;
|
||||
id<MTLTexture> texDisplayPostprocessCustomTouch;
|
||||
|
||||
id<MTLTexture> texDisplaySrcTargetMain;
|
||||
id<MTLTexture> texDisplaySrcTargetTouch;
|
||||
|
||||
id<MTLTexture> texLQ2xLUT;
|
||||
id<MTLTexture> texHQ2xLUT;
|
||||
id<MTLTexture> texHQ3xLUT;
|
||||
id<MTLTexture> texHQ4xLUT;
|
||||
id<MTLTexture> texCurrentHQnxLUT;
|
||||
|
||||
MTLSize load16To32ThreadsPerGroup;
|
||||
MTLSize load16To32ThreadGroupsPerGridNative;
|
||||
MTLSize load16To32ThreadGroupsPerGridCustom;
|
||||
MTLSize fetchThreadsPerGroup;
|
||||
MTLSize fetchThreadGroupsPerGridNative;
|
||||
MTLSize fetchThreadGroupsPerGridCustom;
|
||||
MTLSize deposterizeThreadsPerGroup;
|
||||
MTLSize deposterizeThreadGroupsPerGrid;
|
||||
|
||||
|
@ -92,7 +106,6 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties;
|
|||
@property (readonly, nonatomic) id<MTLCommandQueue> commandQueue;
|
||||
@property (readonly, nonatomic) id<MTLLibrary> defaultLibrary;
|
||||
|
||||
@property (readonly, nonatomic) id<MTLComputePipelineState> load16To32Pipeline;
|
||||
@property (readonly, nonatomic) id<MTLComputePipelineState> deposterizePipeline;
|
||||
@property (readonly, nonatomic) id<MTLRenderPipelineState> hudPipeline;
|
||||
@property (readonly, nonatomic) id<MTLSamplerState> samplerHUDBox;
|
||||
|
@ -109,6 +122,14 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties;
|
|||
@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> texHQ2xLUT;
|
||||
@property (readonly, nonatomic) id<MTLTexture> texHQ3xLUT;
|
||||
|
@ -118,9 +139,9 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties;
|
|||
@property (assign) size_t displayFetchNativeBufferSize;
|
||||
@property (assign) size_t displayFetchCustomBufferSize;
|
||||
|
||||
@property (readonly, nonatomic) MTLSize load16To32ThreadsPerGroup;
|
||||
@property (readonly, nonatomic) MTLSize load16To32ThreadGroupsPerGridNative;
|
||||
@property (assign) MTLSize load16To32ThreadGroupsPerGridCustom;
|
||||
@property (readonly, nonatomic) MTLSize fetchThreadsPerGroup;
|
||||
@property (readonly, nonatomic) MTLSize fetchThreadGroupsPerGridNative;
|
||||
@property (assign) MTLSize fetchThreadGroupsPerGridCustom;
|
||||
@property (readonly, nonatomic) MTLSize deposterizeThreadsPerGroup;
|
||||
@property (readonly, nonatomic) MTLSize deposterizeThreadGroupsPerGrid;
|
||||
|
||||
|
@ -128,7 +149,6 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties;
|
|||
- (void) fetchFromBufferIndex:(const u8)index;
|
||||
- (void) fetchNativeDisplayByID:(const NDSDisplayID)displayID bufferIndex:(const u8)bufferIndex;
|
||||
- (void) fetchCustomDisplayByID:(const NDSDisplayID)displayID bufferIndex:(const u8)bufferIndex;
|
||||
- (void) convertFetch16To32UsingEncoder:(id<MTLComputeCommandEncoder>)cce isMainNative:(BOOL)isMainNative isTouchNative:(BOOL)isTouchNative;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -201,7 +221,7 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties;
|
|||
class MacMetalFetchObject : public GPUClientFetchObject
|
||||
{
|
||||
protected:
|
||||
bool _useCPUFilterPipeline;
|
||||
bool _useDirectToCPUFilterPipeline;
|
||||
uint32_t *_srcNativeCloneMaster;
|
||||
uint32_t *_srcNativeClone[2][2];
|
||||
pthread_rwlock_t _srcCloneRWLock[2][2];
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
@synthesize commandQueue;
|
||||
@synthesize defaultLibrary;
|
||||
|
||||
@synthesize load16To32Pipeline;
|
||||
@synthesize deposterizePipeline;
|
||||
@synthesize hudPipeline;
|
||||
@synthesize samplerHUDBox;
|
||||
|
@ -42,6 +41,14 @@
|
|||
@synthesize texDisplayFetch32CustomMain;
|
||||
@synthesize texDisplayFetch32CustomTouch;
|
||||
|
||||
@synthesize texDisplayPostprocessNativeMain;
|
||||
@synthesize texDisplayPostprocessCustomMain;
|
||||
@synthesize texDisplayPostprocessNativeTouch;
|
||||
@synthesize texDisplayPostprocessCustomTouch;
|
||||
|
||||
@synthesize texDisplaySrcTargetMain;
|
||||
@synthesize texDisplaySrcTargetTouch;
|
||||
|
||||
@synthesize texLQ2xLUT;
|
||||
@synthesize texHQ2xLUT;
|
||||
@synthesize texHQ3xLUT;
|
||||
|
@ -51,9 +58,9 @@
|
|||
@synthesize displayFetchNativeBufferSize;
|
||||
@synthesize displayFetchCustomBufferSize;
|
||||
|
||||
@synthesize load16To32ThreadsPerGroup;
|
||||
@synthesize load16To32ThreadGroupsPerGridNative;
|
||||
@synthesize load16To32ThreadGroupsPerGridCustom;
|
||||
@synthesize fetchThreadsPerGroup;
|
||||
@synthesize fetchThreadGroupsPerGridNative;
|
||||
@synthesize fetchThreadGroupsPerGridCustom;
|
||||
@synthesize deposterizeThreadsPerGroup;
|
||||
@synthesize deposterizeThreadGroupsPerGrid;
|
||||
|
||||
|
@ -77,26 +84,29 @@
|
|||
|
||||
commandQueue = [[device newCommandQueue] retain];
|
||||
defaultLibrary = [[device newDefaultLibrary] retain];
|
||||
load16To32Pipeline = [[device newComputePipelineStateWithFunction:[defaultLibrary newFunctionWithName:@"src16_unpack_unorm1555_to_unorm8888"] error:nil] retain];
|
||||
_fetch555Pipeline = [[device newComputePipelineStateWithFunction:[defaultLibrary newFunctionWithName:@"nds_fetch555"] error:nil] retain];
|
||||
_fetch555ConvertOnlyPipeline = [[device newComputePipelineStateWithFunction:[defaultLibrary newFunctionWithName:@"nds_fetch555ConvertOnly"] error:nil] retain];
|
||||
_fetch666Pipeline = [[device newComputePipelineStateWithFunction:[defaultLibrary newFunctionWithName:@"nds_fetch666"] error:nil] retain];
|
||||
_fetch888Pipeline = [[device newComputePipelineStateWithFunction:[defaultLibrary newFunctionWithName:@"nds_fetch888"] error:nil] retain];
|
||||
deposterizePipeline = [[device newComputePipelineStateWithFunction:[defaultLibrary newFunctionWithName:@"src_filter_deposterize"] error:nil] retain];
|
||||
|
||||
size_t tw = GetNearestPositivePOT((uint32_t)[load16To32Pipeline threadExecutionWidth]);
|
||||
while ( (tw > [load16To32Pipeline threadExecutionWidth]) || (tw > GPU_FRAMEBUFFER_NATIVE_WIDTH) )
|
||||
size_t tw = GetNearestPositivePOT((uint32_t)[_fetch555Pipeline threadExecutionWidth]);
|
||||
while ( (tw > [_fetch555Pipeline threadExecutionWidth]) || (tw > GPU_FRAMEBUFFER_NATIVE_WIDTH) )
|
||||
{
|
||||
tw >>= 1;
|
||||
}
|
||||
|
||||
size_t th = [load16To32Pipeline maxTotalThreadsPerThreadgroup] / tw;
|
||||
size_t th = [_fetch555Pipeline maxTotalThreadsPerThreadgroup] / tw;
|
||||
|
||||
load16To32ThreadsPerGroup = MTLSizeMake(tw, th, 1);
|
||||
load16To32ThreadGroupsPerGridNative = MTLSizeMake(GPU_FRAMEBUFFER_NATIVE_WIDTH / tw,
|
||||
fetchThreadsPerGroup = MTLSizeMake(tw, th, 1);
|
||||
fetchThreadGroupsPerGridNative = MTLSizeMake(GPU_FRAMEBUFFER_NATIVE_WIDTH / tw,
|
||||
GPU_FRAMEBUFFER_NATIVE_HEIGHT / th,
|
||||
1);
|
||||
|
||||
load16To32ThreadGroupsPerGridCustom = load16To32ThreadGroupsPerGridNative;
|
||||
fetchThreadGroupsPerGridCustom = fetchThreadGroupsPerGridNative;
|
||||
|
||||
deposterizeThreadsPerGroup = load16To32ThreadsPerGroup;
|
||||
deposterizeThreadGroupsPerGrid = load16To32ThreadGroupsPerGridNative;
|
||||
deposterizeThreadsPerGroup = fetchThreadsPerGroup;
|
||||
deposterizeThreadGroupsPerGrid = fetchThreadGroupsPerGridNative;
|
||||
|
||||
MTLRenderPipelineDescriptor *hudPipelineDesc = [[MTLRenderPipelineDescriptor alloc] init];
|
||||
[[[hudPipelineDesc colorAttachments] objectAtIndexedSubscript:0] setPixelFormat:MTLPixelFormatBGRA8Unorm];
|
||||
|
@ -139,6 +149,11 @@
|
|||
displayFetchNativeBufferSize = 0;
|
||||
displayFetchCustomBufferSize = 0;
|
||||
|
||||
_bufMasterBrightMode[NDSDisplayID_Main] = [[device newBufferWithLength:sizeof(uint8_t) * GPU_FRAMEBUFFER_NATIVE_HEIGHT options:MTLResourceStorageModeManaged] retain];
|
||||
_bufMasterBrightMode[NDSDisplayID_Touch] = [[device newBufferWithLength:sizeof(uint8_t) * GPU_FRAMEBUFFER_NATIVE_HEIGHT options:MTLResourceStorageModeManaged] retain];
|
||||
_bufMasterBrightIntensity[NDSDisplayID_Main] = [[device newBufferWithLength:sizeof(uint8_t) * GPU_FRAMEBUFFER_NATIVE_HEIGHT options:MTLResourceStorageModeManaged] retain];
|
||||
_bufMasterBrightIntensity[NDSDisplayID_Touch] = [[device newBufferWithLength:sizeof(uint8_t) * GPU_FRAMEBUFFER_NATIVE_HEIGHT options:MTLResourceStorageModeManaged] retain];
|
||||
|
||||
// Set up HUD texture samplers.
|
||||
MTLSamplerDescriptor *samplerDesc = [[MTLSamplerDescriptor alloc] init];
|
||||
[samplerDesc setNormalizedCoordinates:YES];
|
||||
|
@ -189,6 +204,11 @@
|
|||
texDisplayFetch32CustomMain = [[device newTextureWithDescriptor:texDisplayLoad32Desc] retain];
|
||||
texDisplayFetch32CustomTouch = [[device newTextureWithDescriptor:texDisplayLoad32Desc] retain];
|
||||
|
||||
texDisplayPostprocessNativeMain = [[device newTextureWithDescriptor:texDisplayLoad32Desc] retain];
|
||||
texDisplayPostprocessCustomMain = [[device newTextureWithDescriptor:texDisplayLoad32Desc] retain];
|
||||
texDisplayPostprocessNativeTouch = [[device newTextureWithDescriptor:texDisplayLoad32Desc] retain];
|
||||
texDisplayPostprocessCustomTouch = [[device newTextureWithDescriptor:texDisplayLoad32Desc] retain];
|
||||
|
||||
uint16_t *blankBuffer = (uint16_t *)calloc(GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT, sizeof(uint32_t));
|
||||
const MTLRegion texRegionNative = MTLRegionMake2D(0, 0, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT);
|
||||
[texDisplayFetch32NativeMain replaceRegion:texRegionNative
|
||||
|
@ -207,8 +227,28 @@
|
|||
mipmapLevel:0
|
||||
withBytes:blankBuffer
|
||||
bytesPerRow:GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(uint32_t)];
|
||||
|
||||
[texDisplayPostprocessNativeMain replaceRegion:texRegionNative
|
||||
mipmapLevel:0
|
||||
withBytes:blankBuffer
|
||||
bytesPerRow:GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(uint32_t)];
|
||||
[texDisplayPostprocessCustomMain replaceRegion:texRegionNative
|
||||
mipmapLevel:0
|
||||
withBytes:blankBuffer
|
||||
bytesPerRow:GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(uint32_t)];
|
||||
[texDisplayPostprocessNativeTouch replaceRegion:texRegionNative
|
||||
mipmapLevel:0
|
||||
withBytes:blankBuffer
|
||||
bytesPerRow:GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(uint32_t)];
|
||||
[texDisplayPostprocessCustomTouch replaceRegion:texRegionNative
|
||||
mipmapLevel:0
|
||||
withBytes:blankBuffer
|
||||
bytesPerRow:GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(uint32_t)];
|
||||
free(blankBuffer);
|
||||
|
||||
texDisplaySrcTargetMain = [texDisplayFetch32NativeMain retain];
|
||||
texDisplaySrcTargetTouch = [texDisplayFetch32NativeTouch retain];
|
||||
|
||||
// Set up the HQnx LUT textures.
|
||||
SetupHQnxLUTs_Metal(device, texLQ2xLUT, texHQ2xLUT, texHQ3xLUT, texHQ4xLUT);
|
||||
texCurrentHQnxLUT = nil;
|
||||
|
@ -225,11 +265,19 @@
|
|||
|
||||
[commandQueue release];
|
||||
[defaultLibrary release];
|
||||
[load16To32Pipeline release];
|
||||
[_fetch555Pipeline release];
|
||||
[_fetch555ConvertOnlyPipeline release];
|
||||
[_fetch666Pipeline release];
|
||||
[_fetch888Pipeline release];
|
||||
[deposterizePipeline release];
|
||||
[hudPipeline release];
|
||||
[hudIndexBuffer release];
|
||||
|
||||
[_bufMasterBrightMode[NDSDisplayID_Main] release];
|
||||
[_bufMasterBrightMode[NDSDisplayID_Touch] release];
|
||||
[_bufMasterBrightIntensity[NDSDisplayID_Main] release];
|
||||
[_bufMasterBrightIntensity[NDSDisplayID_Touch] release];
|
||||
|
||||
[texDisplayFetch16NativeMain release];
|
||||
[texDisplayFetch16NativeTouch release];
|
||||
[texDisplayFetch32NativeMain release];
|
||||
|
@ -239,6 +287,14 @@
|
|||
[self setTexDisplayFetch32CustomMain:nil];
|
||||
[self setTexDisplayFetch32CustomTouch:nil];
|
||||
|
||||
[self setTexDisplayPostprocessNativeMain:nil];
|
||||
[self setTexDisplayPostprocessCustomMain:nil];
|
||||
[self setTexDisplayPostprocessNativeTouch:nil];
|
||||
[self setTexDisplayPostprocessCustomTouch:nil];
|
||||
|
||||
[self setTexDisplaySrcTargetMain:nil];
|
||||
[self setTexDisplaySrcTargetTouch:nil];
|
||||
|
||||
DeleteHQnxLUTs_Metal(texLQ2xLUT, texHQ2xLUT, texHQ3xLUT, texHQ4xLUT);
|
||||
[self setTexCurrentHQnxLUT:nil];
|
||||
|
||||
|
@ -319,10 +375,243 @@
|
|||
GPUFetchObject->GPUClientFetchObject::FetchFromBufferIndex(index);
|
||||
|
||||
[_fetchEncoder endEncoding];
|
||||
[cb commit];
|
||||
|
||||
pthread_rwlock_unlock([self rwlockFramebufferAtIndex:index]);
|
||||
pthread_mutex_unlock(&_mutexFetch);
|
||||
|
||||
id<MTLTexture> texDisplaySrcTarget[2] = {nil, nil};
|
||||
const NDSDisplayInfo ¤tDisplayInfo = GPUFetchObject->GetFetchDisplayInfoForBufferIndex(index);
|
||||
const bool isMainEnabled = currentDisplayInfo.isDisplayEnabled[NDSDisplayID_Main];
|
||||
const bool isTouchEnabled = currentDisplayInfo.isDisplayEnabled[NDSDisplayID_Touch];
|
||||
|
||||
if (isMainEnabled || isTouchEnabled)
|
||||
{
|
||||
if (isMainEnabled)
|
||||
{
|
||||
if (!currentDisplayInfo.didPerformCustomRender[NDSDisplayID_Main])
|
||||
{
|
||||
texDisplaySrcTarget[NDSDisplayID_Main] = texDisplayFetch32NativeMain;
|
||||
}
|
||||
else
|
||||
{
|
||||
texDisplaySrcTarget[NDSDisplayID_Main] = texDisplayFetch32CustomMain;
|
||||
}
|
||||
}
|
||||
|
||||
if (isTouchEnabled)
|
||||
{
|
||||
if (!currentDisplayInfo.didPerformCustomRender[NDSDisplayID_Touch])
|
||||
{
|
||||
texDisplaySrcTarget[NDSDisplayID_Touch] = texDisplayFetch32NativeTouch;
|
||||
}
|
||||
else
|
||||
{
|
||||
texDisplaySrcTarget[NDSDisplayID_Touch] = texDisplayFetch32CustomTouch;
|
||||
}
|
||||
}
|
||||
|
||||
id<MTLComputeCommandEncoder> cce = [cb computeCommandEncoder];
|
||||
|
||||
if (currentDisplayInfo.colorFormat == NDSColorFormat_BGR555_Rev)
|
||||
{
|
||||
// 16-bit textures aren't handled natively in Metal for macOS, so we need to explicitly convert to 32-bit here.
|
||||
|
||||
if (currentDisplayInfo.needConvertColorFormat[NDSDisplayID_Main] || currentDisplayInfo.needConvertColorFormat[NDSDisplayID_Touch] ||
|
||||
currentDisplayInfo.needApplyMasterBrightness[NDSDisplayID_Main] || currentDisplayInfo.needApplyMasterBrightness[NDSDisplayID_Touch])
|
||||
{
|
||||
[cce setComputePipelineState:_fetch555Pipeline];
|
||||
|
||||
if (isMainEnabled)
|
||||
{
|
||||
memcpy([_bufMasterBrightMode[NDSDisplayID_Main] contents], currentDisplayInfo.masterBrightnessMode[NDSDisplayID_Main], sizeof(uint8_t) * GPU_FRAMEBUFFER_NATIVE_HEIGHT);
|
||||
memcpy([_bufMasterBrightIntensity[NDSDisplayID_Main] contents], currentDisplayInfo.masterBrightnessIntensity[NDSDisplayID_Main], sizeof(uint8_t) * GPU_FRAMEBUFFER_NATIVE_HEIGHT);
|
||||
[_bufMasterBrightMode[NDSDisplayID_Main] didModifyRange:NSMakeRange(0, sizeof(uint8_t) * GPU_FRAMEBUFFER_NATIVE_HEIGHT)];
|
||||
[_bufMasterBrightIntensity[NDSDisplayID_Main] didModifyRange:NSMakeRange(0, sizeof(uint8_t) * GPU_FRAMEBUFFER_NATIVE_HEIGHT)];
|
||||
|
||||
[cce setBuffer:_bufMasterBrightMode[NDSDisplayID_Main] offset:0 atIndex:0];
|
||||
[cce setBuffer:_bufMasterBrightIntensity[NDSDisplayID_Main] offset:0 atIndex:1];
|
||||
|
||||
if (!currentDisplayInfo.didPerformCustomRender[NDSDisplayID_Main])
|
||||
{
|
||||
[cce setTexture:texDisplayFetch16NativeMain atIndex:0];
|
||||
[cce setTexture:[self texDisplayPostprocessNativeMain] atIndex:1];
|
||||
[cce dispatchThreadgroups:fetchThreadGroupsPerGridNative
|
||||
threadsPerThreadgroup:fetchThreadsPerGroup];
|
||||
|
||||
texDisplaySrcTarget[NDSDisplayID_Main] = [self texDisplayPostprocessNativeMain];
|
||||
}
|
||||
else
|
||||
{
|
||||
[cce setTexture:[self texDisplayFetch16CustomMain] atIndex:0];
|
||||
[cce setTexture:[self texDisplayPostprocessCustomMain] atIndex:1];
|
||||
[cce dispatchThreadgroups:[self fetchThreadGroupsPerGridCustom]
|
||||
threadsPerThreadgroup:[self fetchThreadsPerGroup]];
|
||||
|
||||
texDisplaySrcTarget[NDSDisplayID_Main] = [self texDisplayPostprocessCustomMain];
|
||||
}
|
||||
}
|
||||
|
||||
if (isTouchEnabled)
|
||||
{
|
||||
memcpy([_bufMasterBrightMode[NDSDisplayID_Touch] contents], currentDisplayInfo.masterBrightnessMode[NDSDisplayID_Touch], sizeof(uint8_t) * GPU_FRAMEBUFFER_NATIVE_HEIGHT);
|
||||
memcpy([_bufMasterBrightIntensity[NDSDisplayID_Touch] contents], currentDisplayInfo.masterBrightnessIntensity[NDSDisplayID_Touch], sizeof(uint8_t) * GPU_FRAMEBUFFER_NATIVE_HEIGHT);
|
||||
[_bufMasterBrightMode[NDSDisplayID_Touch] didModifyRange:NSMakeRange(0, sizeof(uint8_t) * GPU_FRAMEBUFFER_NATIVE_HEIGHT)];
|
||||
[_bufMasterBrightIntensity[NDSDisplayID_Touch] didModifyRange:NSMakeRange(0, sizeof(uint8_t) * GPU_FRAMEBUFFER_NATIVE_HEIGHT)];
|
||||
|
||||
[cce setBuffer:_bufMasterBrightMode[NDSDisplayID_Touch] offset:0 atIndex:0];
|
||||
[cce setBuffer:_bufMasterBrightIntensity[NDSDisplayID_Touch] offset:0 atIndex:1];
|
||||
|
||||
if (!currentDisplayInfo.didPerformCustomRender[NDSDisplayID_Touch])
|
||||
{
|
||||
[cce setTexture:texDisplayFetch16NativeTouch atIndex:0];
|
||||
[cce setTexture:[self texDisplayPostprocessNativeTouch] atIndex:1];
|
||||
[cce dispatchThreadgroups:fetchThreadGroupsPerGridNative
|
||||
threadsPerThreadgroup:fetchThreadsPerGroup];
|
||||
|
||||
texDisplaySrcTarget[NDSDisplayID_Touch] = [self texDisplayPostprocessNativeTouch];
|
||||
}
|
||||
else
|
||||
{
|
||||
[cce setTexture:[self texDisplayFetch16CustomTouch] atIndex:0];
|
||||
[cce setTexture:[self texDisplayPostprocessCustomTouch] atIndex:1];
|
||||
[cce dispatchThreadgroups:[self fetchThreadGroupsPerGridCustom]
|
||||
threadsPerThreadgroup:[self fetchThreadsPerGroup]];
|
||||
|
||||
texDisplaySrcTarget[NDSDisplayID_Touch] = [self texDisplayPostprocessCustomTouch];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
[cce setComputePipelineState:_fetch555ConvertOnlyPipeline];
|
||||
|
||||
if (isMainEnabled)
|
||||
{
|
||||
if (!currentDisplayInfo.didPerformCustomRender[NDSDisplayID_Main])
|
||||
{
|
||||
[cce setTexture:texDisplayFetch16NativeMain atIndex:0];
|
||||
[cce setTexture:[self texDisplayPostprocessNativeMain] atIndex:1];
|
||||
[cce dispatchThreadgroups:fetchThreadGroupsPerGridNative
|
||||
threadsPerThreadgroup:fetchThreadsPerGroup];
|
||||
|
||||
texDisplaySrcTarget[NDSDisplayID_Main] = [self texDisplayPostprocessNativeMain];
|
||||
}
|
||||
else
|
||||
{
|
||||
[cce setTexture:[self texDisplayFetch16CustomMain] atIndex:0];
|
||||
[cce setTexture:[self texDisplayPostprocessCustomMain] atIndex:1];
|
||||
[cce dispatchThreadgroups:[self fetchThreadGroupsPerGridCustom]
|
||||
threadsPerThreadgroup:[self fetchThreadsPerGroup]];
|
||||
|
||||
texDisplaySrcTarget[NDSDisplayID_Main] = [self texDisplayPostprocessCustomMain];
|
||||
}
|
||||
}
|
||||
|
||||
if (isTouchEnabled)
|
||||
{
|
||||
if (!currentDisplayInfo.didPerformCustomRender[NDSDisplayID_Touch])
|
||||
{
|
||||
[cce setTexture:texDisplayFetch16NativeTouch atIndex:0];
|
||||
[cce setTexture:[self texDisplayPostprocessNativeTouch] atIndex:1];
|
||||
[cce dispatchThreadgroups:fetchThreadGroupsPerGridNative
|
||||
threadsPerThreadgroup:fetchThreadsPerGroup];
|
||||
|
||||
texDisplaySrcTarget[NDSDisplayID_Touch] = [self texDisplayPostprocessNativeTouch];
|
||||
}
|
||||
else
|
||||
{
|
||||
[cce setTexture:[self texDisplayFetch16CustomTouch] atIndex:0];
|
||||
[cce setTexture:[self texDisplayPostprocessCustomTouch] atIndex:1];
|
||||
[cce dispatchThreadgroups:[self fetchThreadGroupsPerGridCustom]
|
||||
threadsPerThreadgroup:[self fetchThreadsPerGroup]];
|
||||
|
||||
texDisplaySrcTarget[NDSDisplayID_Touch] = [self texDisplayPostprocessCustomTouch];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (currentDisplayInfo.needConvertColorFormat[NDSDisplayID_Main] || currentDisplayInfo.needConvertColorFormat[NDSDisplayID_Touch] ||
|
||||
currentDisplayInfo.needApplyMasterBrightness[NDSDisplayID_Main] || currentDisplayInfo.needApplyMasterBrightness[NDSDisplayID_Touch])
|
||||
{
|
||||
if (currentDisplayInfo.colorFormat == NDSColorFormat_BGR666_Rev)
|
||||
{
|
||||
[cce setComputePipelineState:_fetch666Pipeline];
|
||||
}
|
||||
else
|
||||
{
|
||||
[cce setComputePipelineState:_fetch888Pipeline];
|
||||
}
|
||||
|
||||
if (isMainEnabled)
|
||||
{
|
||||
memcpy([_bufMasterBrightMode[NDSDisplayID_Main] contents], currentDisplayInfo.masterBrightnessMode[NDSDisplayID_Main], sizeof(uint8_t) * GPU_FRAMEBUFFER_NATIVE_HEIGHT);
|
||||
memcpy([_bufMasterBrightIntensity[NDSDisplayID_Main] contents], currentDisplayInfo.masterBrightnessIntensity[NDSDisplayID_Main], sizeof(uint8_t) * GPU_FRAMEBUFFER_NATIVE_HEIGHT);
|
||||
[_bufMasterBrightMode[NDSDisplayID_Main] didModifyRange:NSMakeRange(0, sizeof(uint8_t) * GPU_FRAMEBUFFER_NATIVE_HEIGHT)];
|
||||
[_bufMasterBrightIntensity[NDSDisplayID_Main] didModifyRange:NSMakeRange(0, sizeof(uint8_t) * GPU_FRAMEBUFFER_NATIVE_HEIGHT)];
|
||||
|
||||
[cce setBuffer:_bufMasterBrightMode[NDSDisplayID_Main] offset:0 atIndex:0];
|
||||
[cce setBuffer:_bufMasterBrightIntensity[NDSDisplayID_Main] offset:0 atIndex:1];
|
||||
|
||||
if (!currentDisplayInfo.didPerformCustomRender[NDSDisplayID_Main])
|
||||
{
|
||||
[cce setTexture:texDisplayFetch32NativeMain atIndex:0];
|
||||
[cce setTexture:[self texDisplayPostprocessNativeMain] atIndex:1];
|
||||
[cce dispatchThreadgroups:fetchThreadGroupsPerGridNative
|
||||
threadsPerThreadgroup:fetchThreadsPerGroup];
|
||||
|
||||
texDisplaySrcTarget[NDSDisplayID_Main] = [self texDisplayPostprocessNativeMain];
|
||||
}
|
||||
else
|
||||
{
|
||||
[cce setTexture:[self texDisplayFetch32CustomMain] atIndex:0];
|
||||
[cce setTexture:[self texDisplayPostprocessCustomMain] atIndex:1];
|
||||
[cce dispatchThreadgroups:[self fetchThreadGroupsPerGridCustom]
|
||||
threadsPerThreadgroup:[self fetchThreadsPerGroup]];
|
||||
|
||||
texDisplaySrcTarget[NDSDisplayID_Main] = [self texDisplayPostprocessCustomMain];
|
||||
}
|
||||
}
|
||||
|
||||
if (isTouchEnabled)
|
||||
{
|
||||
memcpy([_bufMasterBrightMode[NDSDisplayID_Touch] contents], currentDisplayInfo.masterBrightnessMode[NDSDisplayID_Touch], sizeof(uint8_t) * GPU_FRAMEBUFFER_NATIVE_HEIGHT);
|
||||
memcpy([_bufMasterBrightIntensity[NDSDisplayID_Touch] contents], currentDisplayInfo.masterBrightnessIntensity[NDSDisplayID_Touch], sizeof(uint8_t) * GPU_FRAMEBUFFER_NATIVE_HEIGHT);
|
||||
[_bufMasterBrightMode[NDSDisplayID_Touch] didModifyRange:NSMakeRange(0, sizeof(uint8_t) * GPU_FRAMEBUFFER_NATIVE_HEIGHT)];
|
||||
[_bufMasterBrightIntensity[NDSDisplayID_Touch] didModifyRange:NSMakeRange(0, sizeof(uint8_t) * GPU_FRAMEBUFFER_NATIVE_HEIGHT)];
|
||||
|
||||
[cce setBuffer:_bufMasterBrightMode[NDSDisplayID_Touch] offset:0 atIndex:0];
|
||||
[cce setBuffer:_bufMasterBrightIntensity[NDSDisplayID_Touch] offset:0 atIndex:1];
|
||||
|
||||
if (!currentDisplayInfo.didPerformCustomRender[NDSDisplayID_Touch])
|
||||
{
|
||||
[cce setTexture:texDisplayFetch32NativeTouch atIndex:0];
|
||||
[cce setTexture:[self texDisplayPostprocessNativeTouch] atIndex:1];
|
||||
[cce dispatchThreadgroups:fetchThreadGroupsPerGridNative
|
||||
threadsPerThreadgroup:fetchThreadsPerGroup];
|
||||
|
||||
texDisplaySrcTarget[NDSDisplayID_Touch] = [self texDisplayPostprocessNativeTouch];
|
||||
}
|
||||
else
|
||||
{
|
||||
[cce setTexture:[self texDisplayFetch32CustomTouch] atIndex:0];
|
||||
[cce setTexture:[self texDisplayPostprocessCustomTouch] atIndex:1];
|
||||
[cce dispatchThreadgroups:[self fetchThreadGroupsPerGridCustom]
|
||||
threadsPerThreadgroup:[self fetchThreadsPerGroup]];
|
||||
|
||||
texDisplaySrcTarget[NDSDisplayID_Touch] = [self texDisplayPostprocessCustomTouch];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[cce endEncoding];
|
||||
[cb commit];
|
||||
}
|
||||
|
||||
[self setTexDisplaySrcTargetMain:texDisplaySrcTarget[NDSDisplayID_Main]];
|
||||
[self setTexDisplaySrcTargetTouch:texDisplaySrcTarget[NDSDisplayID_Touch]];
|
||||
}
|
||||
|
||||
- (void) fetchNativeDisplayByID:(const NDSDisplayID)displayID bufferIndex:(const u8)bufferIndex
|
||||
|
@ -375,11 +664,11 @@
|
|||
[texDisplayLoad32Desc setStorageMode:MTLStorageModePrivate];
|
||||
[texDisplayLoad32Desc setUsage:MTLTextureUsageShaderRead | MTLTextureUsageShaderWrite];
|
||||
|
||||
|
||||
if (displayID == NDSDisplayID_Main)
|
||||
{
|
||||
[self setTexDisplayFetch16CustomMain:[device newTextureWithDescriptor:texDisplayLoad16Desc]];
|
||||
[self setTexDisplayFetch32CustomMain:[device newTextureWithDescriptor:texDisplayLoad32Desc]];
|
||||
[self setTexDisplayPostprocessCustomMain:[device newTextureWithDescriptor:texDisplayLoad32Desc]];
|
||||
texFetch16 = [self texDisplayFetch16CustomMain];
|
||||
texFetch32 = [self texDisplayFetch32CustomMain];
|
||||
}
|
||||
|
@ -387,14 +676,15 @@
|
|||
{
|
||||
[self setTexDisplayFetch16CustomTouch:[device newTextureWithDescriptor:texDisplayLoad16Desc]];
|
||||
[self setTexDisplayFetch32CustomTouch:[device newTextureWithDescriptor:texDisplayLoad32Desc]];
|
||||
[self setTexDisplayPostprocessCustomTouch:[device newTextureWithDescriptor:texDisplayLoad32Desc]];
|
||||
texFetch16 = [self texDisplayFetch16CustomTouch];
|
||||
texFetch32 = [self texDisplayFetch32CustomTouch];
|
||||
}
|
||||
|
||||
const size_t tw = load16To32ThreadsPerGroup.width;
|
||||
const size_t th = load16To32ThreadsPerGroup.height;
|
||||
const size_t tw = fetchThreadsPerGroup.width;
|
||||
const size_t th = fetchThreadsPerGroup.height;
|
||||
|
||||
[self setLoad16To32ThreadGroupsPerGridCustom:MTLSizeMake((currentDisplayInfo.customWidth + tw - 1) / tw,
|
||||
[self setFetchThreadGroupsPerGridCustom:MTLSizeMake((currentDisplayInfo.customWidth + tw - 1) / tw,
|
||||
(currentDisplayInfo.customHeight + th - 1) / th,
|
||||
1)];
|
||||
}
|
||||
|
@ -414,42 +704,6 @@
|
|||
destinationOrigin:MTLOriginMake(0, 0, 0)];
|
||||
}
|
||||
|
||||
- (void) convertFetch16To32UsingEncoder:(id<MTLComputeCommandEncoder>)cce isMainNative:(BOOL)isMainNative isTouchNative:(BOOL)isTouchNative
|
||||
{
|
||||
// 16-bit textures aren't handled natively in Metal for macOS, so we need to explicitly convert to 32-bit here.
|
||||
[cce setComputePipelineState:load16To32Pipeline];
|
||||
|
||||
if (isMainNative)
|
||||
{
|
||||
[cce setTexture:texDisplayFetch16NativeMain atIndex:0];
|
||||
[cce setTexture:texDisplayFetch32NativeMain atIndex:1];
|
||||
[cce dispatchThreadgroups:load16To32ThreadGroupsPerGridNative
|
||||
threadsPerThreadgroup:load16To32ThreadsPerGroup];
|
||||
}
|
||||
else
|
||||
{
|
||||
[cce setTexture:texDisplayFetch16CustomMain atIndex:0];
|
||||
[cce setTexture:texDisplayFetch32CustomMain atIndex:1];
|
||||
[cce dispatchThreadgroups:[self load16To32ThreadGroupsPerGridCustom]
|
||||
threadsPerThreadgroup:[self load16To32ThreadsPerGroup]];
|
||||
}
|
||||
|
||||
if (isTouchNative)
|
||||
{
|
||||
[cce setTexture:texDisplayFetch16NativeTouch atIndex:0];
|
||||
[cce setTexture:texDisplayFetch32NativeTouch atIndex:1];
|
||||
[cce dispatchThreadgroups:load16To32ThreadGroupsPerGridNative
|
||||
threadsPerThreadgroup:load16To32ThreadsPerGroup];
|
||||
}
|
||||
else
|
||||
{
|
||||
[cce setTexture:[self texDisplayFetch16CustomTouch] atIndex:0];
|
||||
[cce setTexture:[self texDisplayFetch32CustomTouch] atIndex:1];
|
||||
[cce dispatchThreadgroups:[self load16To32ThreadGroupsPerGridCustom]
|
||||
threadsPerThreadgroup:[self load16To32ThreadsPerGroup]];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation DisplayViewMetalLayer
|
||||
|
@ -963,10 +1217,10 @@
|
|||
const ClientDisplayMode mode = _cdv->GetViewProperties().mode;
|
||||
const bool useDeposterize = _cdv->GetSourceDeposterize();
|
||||
|
||||
_texDisplayOutput[NDSDisplayID_Main] = (!fetchDisplayInfo.didPerformCustomRender[NDSDisplayID_Main]) ? [sharedData texDisplayFetch32NativeMain] : [sharedData texDisplayFetch32CustomMain];
|
||||
_texDisplayOutput[NDSDisplayID_Touch] = (!fetchDisplayInfo.didPerformCustomRender[NDSDisplayID_Touch]) ? [sharedData texDisplayFetch32NativeTouch] : [sharedData texDisplayFetch32CustomTouch];
|
||||
_texDisplayOutput[NDSDisplayID_Main] = [sharedData texDisplaySrcTargetMain];
|
||||
_texDisplayOutput[NDSDisplayID_Touch] = [sharedData texDisplaySrcTargetTouch];
|
||||
|
||||
if (useDeposterize || (_cdv->GetPixelScaler() != VideoFilterTypeID_None) || (fetchDisplayInfo.colorFormat == NDSColorFormat_BGR555_Rev))
|
||||
if (useDeposterize || (_cdv->GetPixelScaler() != VideoFilterTypeID_None))
|
||||
{
|
||||
const bool willFilterOnGPU = _cdv->WillFilterOnGPU();
|
||||
const bool shouldProcessDisplay[2] = { !fetchDisplayInfo.didPerformCustomRender[NDSDisplayID_Main] && fetchDisplayInfo.isDisplayEnabled[NDSDisplayID_Main] && (mode == ClientDisplayMode_Main || mode == ClientDisplayMode_Dual),
|
||||
|
@ -978,13 +1232,6 @@
|
|||
id<MTLCommandBuffer> cb = [[sharedData commandQueue] commandBufferWithUnretainedReferences];
|
||||
id<MTLComputeCommandEncoder> cce = [cb computeCommandEncoder];
|
||||
|
||||
if (fetchDisplayInfo.colorFormat == NDSColorFormat_BGR555_Rev)
|
||||
{
|
||||
[sharedData convertFetch16To32UsingEncoder:cce
|
||||
isMainNative:(fetchDisplayInfo.didPerformCustomRender[NDSDisplayID_Main]) ? NO : YES
|
||||
isTouchNative:(fetchDisplayInfo.didPerformCustomRender[NDSDisplayID_Touch]) ? NO : YES];
|
||||
}
|
||||
|
||||
// Run the video source filters and the pixel scalers
|
||||
if (useDeposterize)
|
||||
{
|
||||
|
@ -992,7 +1239,7 @@
|
|||
|
||||
if (shouldProcessDisplay[NDSDisplayID_Main])
|
||||
{
|
||||
[cce setTexture:[sharedData texDisplayFetch32NativeMain] atIndex:0];
|
||||
[cce setTexture:[sharedData texDisplaySrcTargetMain] atIndex:0];
|
||||
[cce setTexture:_texDisplaySrcDeposterize[NDSDisplayID_Main][0] atIndex:1];
|
||||
[cce dispatchThreadgroups:[sharedData deposterizeThreadGroupsPerGrid]
|
||||
threadsPerThreadgroup:[sharedData deposterizeThreadsPerGroup]];
|
||||
|
@ -1007,7 +1254,7 @@
|
|||
|
||||
if (shouldProcessDisplay[NDSDisplayID_Touch])
|
||||
{
|
||||
[cce setTexture:[sharedData texDisplayFetch32NativeTouch] atIndex:0];
|
||||
[cce setTexture:[sharedData texDisplaySrcTargetTouch] atIndex:0];
|
||||
[cce setTexture:_texDisplaySrcDeposterize[NDSDisplayID_Touch][0] atIndex:1];
|
||||
[cce dispatchThreadgroups:[sharedData deposterizeThreadGroupsPerGrid]
|
||||
threadsPerThreadgroup:[sharedData deposterizeThreadsPerGroup]];
|
||||
|
@ -1048,17 +1295,15 @@
|
|||
}
|
||||
|
||||
[cce endEncoding];
|
||||
[cb commit];
|
||||
|
||||
// If the pixel scaler didn't run on the GPU, run the pixel scaler on the CPU after the command buffer commit.
|
||||
// If the pixel scaler didn't already run on the GPU, then run the pixel scaler on the CPU.
|
||||
if ( (_cdv->GetPixelScaler() != VideoFilterTypeID_None) && !willFilterOnGPU )
|
||||
{
|
||||
id<MTLBlitCommandEncoder> bce = [cb blitCommandEncoder];
|
||||
|
||||
if (useDeposterize)
|
||||
{
|
||||
// Hybrid CPU/GPU-based path (may cause a performance hit on pixel download)
|
||||
id<MTLCommandBuffer> cpuFilterSrcCB = [[sharedData commandQueue] commandBufferWithUnretainedReferences];
|
||||
id<MTLBlitCommandEncoder> bce = [cpuFilterSrcCB blitCommandEncoder];
|
||||
|
||||
if (shouldProcessDisplay[NDSDisplayID_Main])
|
||||
{
|
||||
[bce copyFromTexture:_texDisplaySrcDeposterize[NDSDisplayID_Main][1]
|
||||
|
@ -1088,9 +1333,6 @@
|
|||
|
||||
[bce synchronizeResource:[self bufCPUFilterSrcTouch]];
|
||||
}
|
||||
|
||||
[bce endEncoding];
|
||||
[cpuFilterSrcCB commit];
|
||||
}
|
||||
|
||||
pthread_mutex_lock(_cdv->GetMutexProcessPtr());
|
||||
|
@ -1105,9 +1347,6 @@
|
|||
vfTouch->RunFilter();
|
||||
}
|
||||
|
||||
id<MTLCommandBuffer> cpuFilterDstCB = [[sharedData commandQueue] commandBufferWithUnretainedReferences];
|
||||
id<MTLBlitCommandEncoder> bce = [cpuFilterDstCB blitCommandEncoder];
|
||||
|
||||
if (shouldProcessDisplay[NDSDisplayID_Main])
|
||||
{
|
||||
[[self bufCPUFilterDstMain] didModifyRange:NSMakeRange(0, vfMain->GetDstWidth() * vfMain->GetDstHeight() * sizeof(uint32_t))];
|
||||
|
@ -1142,11 +1381,12 @@
|
|||
_texDisplayOutput[NDSDisplayID_Touch] = [self texDisplayPixelScaleTouch];
|
||||
}
|
||||
|
||||
[bce endEncoding];
|
||||
[cpuFilterDstCB commit];
|
||||
|
||||
pthread_mutex_unlock(_cdv->GetMutexProcessPtr());
|
||||
|
||||
[bce endEncoding];
|
||||
}
|
||||
|
||||
[cb commit];
|
||||
}
|
||||
|
||||
// Update the texture coordinates
|
||||
|
@ -1347,7 +1587,7 @@
|
|||
|
||||
MacMetalFetchObject::MacMetalFetchObject()
|
||||
{
|
||||
_useCPUFilterPipeline = true;
|
||||
_useDirectToCPUFilterPipeline = true;
|
||||
|
||||
pthread_rwlock_init(&_srcCloneRWLock[NDSDisplayID_Main][0], NULL);
|
||||
pthread_rwlock_init(&_srcCloneRWLock[NDSDisplayID_Touch][0], NULL);
|
||||
|
@ -1409,24 +1649,26 @@ void MacMetalFetchObject::SetFetchBuffers(const NDSDisplayInfo ¤tDisplayIn
|
|||
void MacMetalFetchObject::FetchFromBufferIndex(const u8 index)
|
||||
{
|
||||
MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)this->_clientData;
|
||||
this->_useCPUFilterPipeline = ([sharedViewObject numberViewsUsingCPUFiltering] > 0);
|
||||
this->_useDirectToCPUFilterPipeline = ([sharedViewObject numberViewsUsingDirectToCPUFiltering] > 0);
|
||||
|
||||
[(MetalDisplayViewSharedData *)this->_clientData fetchFromBufferIndex:index];
|
||||
}
|
||||
|
||||
void MacMetalFetchObject::_FetchNativeDisplayByID(const NDSDisplayID displayID, const u8 bufferIndex)
|
||||
{
|
||||
if (this->_useCPUFilterPipeline)
|
||||
if (this->_useDirectToCPUFilterPipeline)
|
||||
{
|
||||
GPU->PostprocessDisplay(displayID, this->_fetchDisplayInfo[bufferIndex]);
|
||||
|
||||
pthread_rwlock_wrlock(&this->_srcCloneRWLock[displayID][bufferIndex]);
|
||||
|
||||
if (_fetchDisplayInfo[bufferIndex].pixelBytes == 2)
|
||||
if (this->_fetchDisplayInfo[bufferIndex].pixelBytes == 2)
|
||||
{
|
||||
ColorspaceConvertBuffer555To8888Opaque<false, false>((const uint16_t *)_fetchDisplayInfo[bufferIndex].nativeBuffer[displayID], this->_srcNativeClone[displayID][bufferIndex], GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT);
|
||||
ColorspaceConvertBuffer555To8888Opaque<false, false>((const uint16_t *)this->_fetchDisplayInfo[bufferIndex].nativeBuffer[displayID], this->_srcNativeClone[displayID][bufferIndex], GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT);
|
||||
}
|
||||
else
|
||||
{
|
||||
ColorspaceConvertBuffer888XTo8888Opaque<false, false>((const uint32_t *)_fetchDisplayInfo[bufferIndex].nativeBuffer[displayID], this->_srcNativeClone[displayID][bufferIndex], GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT);
|
||||
ColorspaceConvertBuffer888XTo8888Opaque<false, false>((const uint32_t *)this->_fetchDisplayInfo[bufferIndex].nativeBuffer[displayID], this->_srcNativeClone[displayID][bufferIndex], GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT);
|
||||
}
|
||||
|
||||
pthread_rwlock_unlock(&this->_srcCloneRWLock[displayID][bufferIndex]);
|
||||
|
|
|
@ -58,6 +58,8 @@ float DistYCbCr(const float3 pixA, const float3 pixB);
|
|||
bool IsPixEqual(const float3 pixA, const float3 pixB);
|
||||
bool IsBlendingNeeded(const int4 blend);
|
||||
|
||||
float3 nds_apply_master_brightness(const float3 inColor, const uchar mode, const float intensity);
|
||||
|
||||
constexpr sampler genSampler = sampler(coord::pixel, address::clamp_to_edge, filter::nearest);
|
||||
constexpr sampler outputSamplerBilinear = sampler(coord::pixel, address::clamp_to_edge, filter::linear);
|
||||
|
||||
|
@ -395,13 +397,31 @@ fragment float4 output_filter_lanczos3(const DisplayVtx vtx [[stage_in]], const
|
|||
return float4(outFragment.rgb, 1.0f);
|
||||
}
|
||||
|
||||
#pragma mark Conversion Filters
|
||||
#pragma mark NDS Emulation Functions
|
||||
|
||||
//---------------------------------------
|
||||
// Input Pixel Mapping: 00
|
||||
//
|
||||
// Output Pixel Mapping: 00
|
||||
kernel void src16_unpack_unorm1555_to_unorm8888(const uint2 position [[thread_position_in_grid]],
|
||||
kernel void nds_fetch555(const uint2 position [[thread_position_in_grid]],
|
||||
const constant uchar *brightnessMode [[buffer(0)]],
|
||||
const constant uchar *brightnessIntensity [[buffer(1)]],
|
||||
const texture2d<ushort, access::read> inTexture [[texture(0)]],
|
||||
texture2d<float, access::write> outTexture [[texture(1)]])
|
||||
{
|
||||
const uint h = inTexture.get_height();
|
||||
|
||||
if ( (position.x > inTexture.get_width() - 1) || (position.y > h - 1) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const float4 inColor = unpack_unorm1555_to_unorm8888( (ushort)inTexture.read(position).r );
|
||||
float3 outColor = inColor.rgb;
|
||||
|
||||
const uint line = uint(((float)position.y + 0.01f) / ((float)h / 192.0f));
|
||||
outColor = nds_apply_master_brightness(outColor, brightnessMode[line], (float)brightnessIntensity[line] / 16.0f);
|
||||
|
||||
outTexture.write(float4(outColor, 1.0f), position);
|
||||
}
|
||||
|
||||
kernel void nds_fetch555ConvertOnly(const uint2 position [[thread_position_in_grid]],
|
||||
const texture2d<ushort, access::read> inTexture [[texture(0)]],
|
||||
texture2d<float, access::write> outTexture [[texture(1)]])
|
||||
{
|
||||
|
@ -410,7 +430,71 @@ kernel void src16_unpack_unorm1555_to_unorm8888(const uint2 position [[thread_po
|
|||
return;
|
||||
}
|
||||
|
||||
outTexture.write( unpack_unorm1555_to_unorm8888( (ushort)inTexture.read(position).r ), position );
|
||||
const float4 outColor = unpack_unorm1555_to_unorm8888( (ushort)inTexture.read(position).r );
|
||||
outTexture.write(float4(outColor.rgb, 1.0f), position);
|
||||
}
|
||||
|
||||
kernel void nds_fetch666(const uint2 position [[thread_position_in_grid]],
|
||||
const constant uchar *brightnessMode [[buffer(0)]],
|
||||
const constant uchar *brightnessIntensity [[buffer(1)]],
|
||||
const texture2d<float, access::read> inTexture [[texture(0)]],
|
||||
texture2d<float, access::write> outTexture [[texture(1)]])
|
||||
{
|
||||
const uint h = inTexture.get_height();
|
||||
|
||||
if ( (position.x > inTexture.get_width() - 1) || (position.y > h - 1) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const float4 inColor = inTexture.read(position);
|
||||
float3 outColor = inColor.rgb * float3(255.0f/63.0f);
|
||||
|
||||
const uint line = uint(((float)position.y + 0.01f) / ((float)h / 192.0f));
|
||||
outColor = nds_apply_master_brightness(outColor, brightnessMode[line], (float)brightnessIntensity[line] / 16.0f);
|
||||
|
||||
outTexture.write(float4(outColor, 1.0f), position);
|
||||
}
|
||||
|
||||
kernel void nds_fetch888(const uint2 position [[thread_position_in_grid]],
|
||||
const constant uchar *brightnessMode [[buffer(0)]],
|
||||
const constant uchar *brightnessIntensity [[buffer(1)]],
|
||||
const texture2d<float, access::read> inTexture [[texture(0)]],
|
||||
texture2d<float, access::write> outTexture [[texture(1)]])
|
||||
{
|
||||
const uint h = inTexture.get_height();
|
||||
|
||||
if ( (position.x > inTexture.get_width() - 1) || (position.y > h - 1) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const float4 inColor = inTexture.read(position);
|
||||
float3 outColor = inColor.rgb;
|
||||
|
||||
const uint line = uint(((float)position.y + 0.01f) / ((float)h / 192.0f));
|
||||
outColor = nds_apply_master_brightness(outColor, brightnessMode[line], (float)brightnessIntensity[line] / 16.0f);
|
||||
|
||||
outTexture.write(float4(outColor, 1.0f), position);
|
||||
}
|
||||
|
||||
float3 nds_apply_master_brightness(const float3 inColor, const uchar mode, const float intensity)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case 1:
|
||||
return (inColor + ((1.0f - inColor) * intensity));
|
||||
break;
|
||||
|
||||
case 2:
|
||||
return (inColor - (inColor * intensity));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return inColor;
|
||||
}
|
||||
|
||||
#pragma mark Source Filters
|
||||
|
|
|
@ -199,7 +199,7 @@ void MacOGLClientFetchObject::SetFetchBuffers(const NDSDisplayInfo ¤tDispl
|
|||
void MacOGLClientFetchObject::FetchFromBufferIndex(const u8 index)
|
||||
{
|
||||
MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)this->_clientData;
|
||||
this->_useCPUFilterPipeline = ([sharedViewObject numberViewsUsingCPUFiltering] > 0);
|
||||
this->_useDirectToCPUFilterPipeline = ([sharedViewObject numberViewsUsingDirectToCPUFiltering] > 0);
|
||||
|
||||
pthread_rwlock_rdlock([sharedViewObject rwlockFramebufferAtIndex:index]);
|
||||
|
||||
|
|
|
@ -180,9 +180,8 @@
|
|||
// Init the DS emulation core.
|
||||
CocoaDSCore *newCore = [[[CocoaDSCore alloc] init] autorelease];
|
||||
MacClientSharedObject *sharedViewObject = [[newCore cdsGPU] sharedData];
|
||||
[NSThread detachNewThreadSelector:@selector(runThread:) toTarget:sharedViewObject withObject:nil];
|
||||
|
||||
// Wait until the SPU is finished starting up.
|
||||
[NSThread detachNewThreadSelector:@selector(runThread:) toTarget:sharedViewObject withObject:nil];
|
||||
while ([sharedViewObject thread] == nil)
|
||||
{
|
||||
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01]];
|
||||
|
@ -206,8 +205,6 @@
|
|||
|
||||
// Start up the threads for our outputs.
|
||||
[NSThread detachNewThreadSelector:@selector(runThread:) toTarget:newSpeaker withObject:nil];
|
||||
|
||||
// Wait until the SPU is finished starting up.
|
||||
while ([newSpeaker thread] == nil)
|
||||
{
|
||||
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01]];
|
||||
|
|
Loading…
Reference in New Issue