- Improve the heuristics in determining when custom-sized rendering and custom-sized output is needed.
This commit is contained in:
rogerman 2016-02-23 03:52:27 +00:00
parent 782b60b824
commit c98e669d74
2 changed files with 146 additions and 130 deletions

View File

@ -361,6 +361,11 @@ void GPUEngineBase::_Reset_Base()
this->_BGLayer[GPULayerID_BG2].size = GPUEngineBase::_BGLayerSizeLUT[BGType_Affine][1];
this->_BGLayer[GPULayerID_BG3].size = GPUEngineBase::_BGLayerSizeLUT[BGType_Affine][1];
this->_BGLayer[GPULayerID_BG0].baseType = BGType_Invalid;
this->_BGLayer[GPULayerID_BG1].baseType = BGType_Invalid;
this->_BGLayer[GPULayerID_BG2].baseType = BGType_Invalid;
this->_BGLayer[GPULayerID_BG3].baseType = BGType_Invalid;
this->_BGLayer[GPULayerID_BG0].type = BGType_Invalid;
this->_BGLayer[GPULayerID_BG1].type = BGType_Invalid;
this->_BGLayer[GPULayerID_BG2].type = BGType_Invalid;
@ -406,6 +411,7 @@ void GPUEngineBase::_Reset_Base()
this->_needUpdateWINH[1] = true;
this->isCustomRenderingNeeded = false;
this->isCustomOutputSize = false;
this->vramBGLayer = VRAM_NO_3D_USAGE;
this->vramBlockBGIndex = VRAM_NO_3D_USAGE;
this->vramBlockOBJIndex = VRAM_NO_3D_USAGE;
@ -778,6 +784,8 @@ void GPUEngineBase::ParseReg_BGnCNT()
//clarify affine ext modes
BGType mode = GPUEngineBase::_mode2type[DISPCNT.BG_Mode][LAYERID];
this->_BGLayer[LAYERID].baseType = mode;
if (mode == BGType_AffineExt)
{
//see: http://nocash.emubase.de/gbatek.htm#dsvideobgmodescontrol
@ -3519,9 +3527,8 @@ void GPUEngineBase::_UpdateWINH()
void GPUEngineBase::UpdateVRAM3DUsageProperties_BGLayer(const size_t bankIndex, VRAM3DUsageProperties &outProperty)
{
const IOREG_DISPCNT &DISPCNT = this->_IORegisterMap->DISPCNT;
const bool isBG2UsingVRAM = (DISPCNT.BG2_Enable == 1) && (this->_BGLayer[GPULayerID_BG2].type == BGType_AffineExt_Direct) && (this->_BGLayer[GPULayerID_BG2].size.width == 256) && (this->_BGLayer[GPULayerID_BG2].size.height == 256);
const bool isBG3UsingVRAM = (DISPCNT.BG3_Enable == 1) && (this->_BGLayer[GPULayerID_BG3].type == BGType_AffineExt_Direct) && (this->_BGLayer[GPULayerID_BG3].size.width == 256) && (this->_BGLayer[GPULayerID_BG3].size.height == 256);
const bool isBG2UsingVRAM = this->_enableLayer[GPULayerID_BG2] && (this->_BGLayer[GPULayerID_BG2].type == BGType_AffineExt_Direct) && (this->_BGLayer[GPULayerID_BG2].size.width == 256) && (this->_BGLayer[GPULayerID_BG2].size.height == 256);
const bool isBG3UsingVRAM = this->_enableLayer[GPULayerID_BG3] && (this->_BGLayer[GPULayerID_BG3].type == BGType_AffineExt_Direct) && (this->_BGLayer[GPULayerID_BG3].size.width == 256) && (this->_BGLayer[GPULayerID_BG3].size.height == 256);
u8 selectedBGLayer = VRAM_NO_3D_USAGE;
if (!isBG2UsingVRAM && !isBG3UsingVRAM)
@ -3530,15 +3537,15 @@ void GPUEngineBase::UpdateVRAM3DUsageProperties_BGLayer(const size_t bankIndex,
}
else if (!isBG2UsingVRAM && isBG3UsingVRAM)
{
selectedBGLayer = (this->_BGLayer[GPULayerID_BG3].priority <= this->_BGLayer[GPULayerID_BG0].priority) ? GPULayerID_BG3 : VRAM_NO_3D_USAGE;
selectedBGLayer = GPULayerID_BG3;
}
else if (isBG2UsingVRAM && !isBG3UsingVRAM)
{
selectedBGLayer = (this->_BGLayer[GPULayerID_BG2].priority <= this->_BGLayer[GPULayerID_BG0].priority) ? GPULayerID_BG2 : VRAM_NO_3D_USAGE;
selectedBGLayer = GPULayerID_BG2;
}
else if (isBG2UsingVRAM && isBG3UsingVRAM)
{
selectedBGLayer = (this->_BGLayer[GPULayerID_BG3].priority <= this->_BGLayer[GPULayerID_BG2].priority) ? ((this->_BGLayer[GPULayerID_BG3].priority <= this->_BGLayer[GPULayerID_BG0].priority) ? GPULayerID_BG3 : VRAM_NO_3D_USAGE) : ((this->_BGLayer[GPULayerID_BG2].priority <= this->_BGLayer[GPULayerID_BG0].priority) ? GPULayerID_BG2 : VRAM_NO_3D_USAGE);
selectedBGLayer = (this->_BGLayer[GPULayerID_BG3].priority <= this->_BGLayer[GPULayerID_BG2].priority) ? GPULayerID_BG3 : GPULayerID_BG2;
}
if (selectedBGLayer != VRAM_NO_3D_USAGE)
@ -3559,14 +3566,13 @@ void GPUEngineBase::UpdateVRAM3DUsageProperties_BGLayer(const size_t bankIndex,
}
this->vramBGLayer = selectedBGLayer;
this->vramBlockBGIndex = bankIndex;
this->isCustomRenderingNeeded = (selectedBGLayer != VRAM_NO_3D_USAGE);
this->vramBlockBGIndex = (selectedBGLayer != VRAM_NO_3D_USAGE) ? bankIndex : VRAM_NO_3D_USAGE;
}
void GPUEngineBase::UpdateVRAM3DUsageProperties_OBJLayer(const size_t bankIndex, VRAM3DUsageProperties &outProperty)
{
const IOREG_DISPCNT &DISPCNT = this->_IORegisterMap->DISPCNT;
if ((DISPCNT.OBJ_Enable != 1) || (DISPCNT.OBJ_BMP_mapping != 0) || (DISPCNT.OBJ_BMP_2D_dim != 1))
if (!this->_enableLayer[GPULayerID_OBJ] || (DISPCNT.OBJ_BMP_mapping != 0) || (DISPCNT.OBJ_BMP_2D_dim == 0))
{
return;
}
@ -3586,7 +3592,6 @@ void GPUEngineBase::UpdateVRAM3DUsageProperties_OBJLayer(const size_t bankIndex,
if( (vramAddress == (DISPCAPCNT.VRAMWriteOffset * ADDRESS_STEP_32KB)) && (sprSize.width == 64) && (sprSize.height == 64) )
{
this->vramBlockOBJIndex = bankIndex;
this->isCustomRenderingNeeded = true;
return;
}
}
@ -3596,10 +3601,9 @@ void GPUEngineBase::UpdateVRAM3DUsageProperties_OBJLayer(const size_t bankIndex,
template <GPULayerID LAYERID, bool ISDEBUGRENDER, bool MOSAIC, bool NOWINDOWSENABLEDHINT, bool COLOREFFECTDISABLEDHINT, bool ISCUSTOMRENDERINGNEEDED>
void GPUEngineBase::_RenderLine_LayerBG_Final(u16 *dstColorLine, const u16 lineIndex)
{
const BGType bgType = GPUEngineBase::_mode2type[this->_IORegisterMap->DISPCNT.BG_Mode][LAYERID];
bool useCustomVRAM = false;
switch (bgType)
switch (this->_BGLayer[LAYERID].baseType)
{
case BGType_Text: this->_LineText<LAYERID, ISDEBUGRENDER, MOSAIC, NOWINDOWSENABLEDHINT, COLOREFFECTDISABLEDHINT, ISCUSTOMRENDERINGNEEDED>(dstColorLine, lineIndex); break;
case BGType_Affine: this->_LineRot<LAYERID, ISDEBUGRENDER, MOSAIC, NOWINDOWSENABLEDHINT, COLOREFFECTDISABLEDHINT, ISCUSTOMRENDERINGNEEDED>(dstColorLine, lineIndex); break;
@ -3698,21 +3702,14 @@ void GPUEngineBase::RenderLayerBG(u16 *dstColorBuffer)
}
}
template<bool ISCUSTOMRENDERINGNEEDED>
void GPUEngineBase::_HandleDisplayModeOff(u16 *dstColorLine, const size_t l, const size_t dstLineWidth, const size_t dstLineCount)
void GPUEngineBase::_HandleDisplayModeOff(u16 *dstColorLine)
{
// Native rendering only.
// In this display mode, the display is cleared to white.
if (ISCUSTOMRENDERINGNEEDED)
{
memset_u16(dstColorLine, 0x7FFF, dstLineWidth * dstLineCount);
}
else
{
memset_u16_fast<GPU_FRAMEBUFFER_NATIVE_WIDTH>(dstColorLine, 0x7FFF);
}
}
template<bool ISCUSTOMRENDERINGNEEDED>
template<bool ISCUSTOMOUTPUTSIZE>
void GPUEngineBase::_HandleDisplayModeNormal(u16 *dstColorLine, const size_t l, const size_t dstLineWidth, const size_t dstLineCount)
{
//do nothing: it has already been generated into the right place
@ -4090,12 +4087,12 @@ void GPUEngineA::SetCustomFramebufferSize(size_t w, size_t h)
}
bool GPUEngineA::Is3DRenderedLayerNeeded()
bool GPUEngineA::WillRender3DLayer()
{
return ( this->_enableLayer[GPULayerID_BG0] && (this->_IORegisterMap->DISPCNT.BG0_3D != 0) );
return ( this->_enableLayer[GPULayerID_BG0] && (this->_IORegisterMap->DISPCNT.BG0_Enable != 0) && (this->_IORegisterMap->DISPCNT.BG0_3D != 0) );
}
bool GPUEngineA::Is3DCapturingNeeded()
bool GPUEngineA::WillCapture3DLayerDirect()
{
const IOREG_DISPCAPCNT &DISPCAPCNT = this->_IORegisterMap->DISPCAPCNT;
return ( (DISPCAPCNT.CaptureEnable != 0) && (vramConfiguration.banks[DISPCAPCNT.VRAMWriteBlock].purpose == VramConfiguration::LCDC) && (DISPCAPCNT.SrcA != 0) );
@ -4131,7 +4128,7 @@ void GPUEngineA::RenderLine(const u16 l)
switch (displayMode)
{
case GPUDisplayMode_Off: // Display Off(Display white)
this->_HandleDisplayModeOff<ISCUSTOMRENDERINGNEEDED>(dstColorLine, l, dstLineWidth, dstLineCount);
this->_HandleDisplayModeOff(dstColorLine);
break;
case GPUDisplayMode_Normal: // Display BG and OBJ layers
@ -4143,7 +4140,7 @@ void GPUEngineA::RenderLine(const u16 l)
break;
case GPUDisplayMode_MainMemory: // Display memory FIFO
this->_HandleDisplayModeMainMemory<ISCUSTOMRENDERINGNEEDED>(dstColorLine, l, dstLineWidth, dstLineCount);
this->_HandleDisplayModeMainMemory(dstColorLine);
break;
}
@ -4212,13 +4209,7 @@ void GPUEngineA::_RenderLine_Layer(const u16 l, u16 *dstColorLine, const size_t
const GPULayerID layerID = (GPULayerID)item->BGs[i];
if (this->_enableLayer[layerID])
{
// When determining whether to render the BG0 layer as a 3D layer, we only need to
// check the DISPCNT.BG0_3D flag. There is no need to check the DISPCNT.BG0_Enable
// flag here, as this flag could be disabled while the DISPCNT.BG0_3D flag is enabled.
//
// Test case: During some conversations in Advance Wars: Dual Strike, the minimap
// will be rendered as garbage pixels unless the DISPCNT.BG0_Enable flag is ignored.
if (layerID == GPULayerID_BG0 && (this->_IORegisterMap->DISPCNT.BG0_3D != 0))
if ( (layerID == GPULayerID_BG0) && this->WillRender3DLayer() )
{
const FragmentColor *__restrict framebuffer3D = CurrentRenderer->GetFramebuffer();
if (framebuffer3D == NULL)
@ -4361,7 +4352,7 @@ void GPUEngineA::_RenderLine_Layer(const u16 l, u16 *dstColorLine, const size_t
}
}
template<bool ISCUSTOMRENDERINGNEEDED, size_t CAPTURELENGTH>
template<bool DIDCUSTOMRENDER, size_t CAPTURELENGTH>
void GPUEngineA::_RenderLine_DisplayCapture(u16 *dstColorLine, const u16 l)
{
assert( (CAPTURELENGTH == GPU_FRAMEBUFFER_NATIVE_WIDTH/2) || (CAPTURELENGTH == GPU_FRAMEBUFFER_NATIVE_WIDTH) );
@ -4370,7 +4361,7 @@ void GPUEngineA::_RenderLine_DisplayCapture(u16 *dstColorLine, const u16 l)
const IOREG_DISPCAPCNT &DISPCAPCNT = this->_IORegisterMap->DISPCAPCNT;
const NDSDisplayInfo &dispInfo = GPU->GetDisplayInfo();
VRAM3DUsageProperties &vramUsageProperty = GPU->GetVRAM3DUsageProperties();
VRAM3DUsageProperties &vramUsageProperty = GPU->GetRenderProperties();
const u8 vramWriteBlock = DISPCAPCNT.VRAMWriteBlock;
const u8 vramReadBlock = DISPCNT.VRAM_Block;
@ -4406,19 +4397,19 @@ void GPUEngineA::_RenderLine_DisplayCapture(u16 *dstColorLine, const u16 l)
case 0: // Capture screen (BG + OBJ + 3D)
{
//INFO("Capture screen (BG + OBJ + 3D)\n");
this->_RenderLine_DispCapture_Copy<0, CAPTURELENGTH, !ISCUSTOMRENDERINGNEEDED, true>(srcA, cap_dst, CAPTURELENGTH, 1);
this->_RenderLine_DispCapture_Copy<0, CAPTURELENGTH, !DIDCUSTOMRENDER, true>(srcA, cap_dst, CAPTURELENGTH, 1);
break;
}
case 1: // Capture 3D
{
//INFO("Capture 3D\n");
this->_RenderLine_DispCapture_Copy<1, CAPTURELENGTH, !ISCUSTOMRENDERINGNEEDED, true>(srcA, cap_dst, CAPTURELENGTH, 1);
this->_RenderLine_DispCapture_Copy<1, CAPTURELENGTH, !DIDCUSTOMRENDER, true>(srcA, cap_dst, CAPTURELENGTH, 1);
break;
}
}
vramUsageProperty.isBlockUsed[vramWriteBlock] = ISCUSTOMRENDERINGNEEDED;
vramUsageProperty.isCustomBlockUsed[vramWriteBlock] = DIDCUSTOMRENDER;
break;
}
@ -4429,16 +4420,16 @@ void GPUEngineA::_RenderLine_DisplayCapture(u16 *dstColorLine, const u16 l)
{
case 0: // Capture VRAM
{
if (ISCUSTOMRENDERINGNEEDED && vramUsageProperty.isBlockUsed[vramReadBlock])
if (vramUsageProperty.isCustomBlockUsed[vramReadBlock])
{
this->_RenderLine_DispCapture_Copy<0, CAPTURELENGTH, false, true>(srcB, cap_dst, CAPTURELENGTH, 1);
vramUsageProperty.isCustomBlockUsed[vramWriteBlock] = true;
}
else
{
this->_RenderLine_DispCapture_Copy<0, CAPTURELENGTH, true, true>(srcB, cap_dst, CAPTURELENGTH, 1);
vramUsageProperty.isCustomBlockUsed[vramWriteBlock] = false;
}
vramUsageProperty.isBlockUsed[vramWriteBlock] = vramUsageProperty.isBlockUsed[vramReadBlock];
break;
}
@ -4446,42 +4437,37 @@ void GPUEngineA::_RenderLine_DisplayCapture(u16 *dstColorLine, const u16 l)
{
this->_RenderLine_DispCapture_FIFOToBuffer(fifoLine);
this->_RenderLine_DispCapture_Copy<1, CAPTURELENGTH, true, true>(srcB, cap_dst, CAPTURELENGTH, 1);
vramUsageProperty.isBlockUsed[vramWriteBlock] = false;
vramUsageProperty.isCustomBlockUsed[vramWriteBlock] = false;
break;
}
}
break;
}
default: // Capture source is SourceA+B blended
{
//INFO("Capture source is SourceA+B blended\n");
if (DISPCAPCNT.SrcB == 1)
if ( (DISPCAPCNT.SrcB == 0) && vramUsageProperty.isCustomBlockUsed[vramReadBlock] )
{
this->_RenderLine_DispCapture_Blend<CAPTURELENGTH, !DIDCUSTOMRENDER, false, true>(srcA, srcB, cap_dst, CAPTURELENGTH, 1);
vramUsageProperty.isCustomBlockUsed[vramWriteBlock] = true;
}
else
{
if (DISPCAPCNT.SrcB != 0)
{
// fifo - tested by splinter cell chaos theory thermal view
this->_RenderLine_DispCapture_FIFOToBuffer(fifoLine);
this->_RenderLine_DispCapture_Blend<CAPTURELENGTH, !ISCUSTOMRENDERINGNEEDED, true, true>(srcA, srcB, cap_dst, CAPTURELENGTH, 1);
}
else
{
if (vramUsageProperty.isBlockUsed[vramReadBlock])
{
this->_RenderLine_DispCapture_Blend<CAPTURELENGTH, !ISCUSTOMRENDERINGNEEDED, false, true>(srcA, srcB, cap_dst, CAPTURELENGTH, 1);
}
else
{
this->_RenderLine_DispCapture_Blend<CAPTURELENGTH, !ISCUSTOMRENDERINGNEEDED, true, true>(srcA, srcB, cap_dst, CAPTURELENGTH, 1);
}
}
vramUsageProperty.isBlockUsed[vramWriteBlock] = ISCUSTOMRENDERINGNEEDED || vramUsageProperty.isBlockUsed[vramReadBlock];
this->_RenderLine_DispCapture_Blend<CAPTURELENGTH, !DIDCUSTOMRENDER, true, true>(srcA, srcB, cap_dst, CAPTURELENGTH, 1);
vramUsageProperty.isCustomBlockUsed[vramWriteBlock] = DIDCUSTOMRENDER;
}
break;
}
}
if (ISCUSTOMRENDERINGNEEDED)
if (DIDCUSTOMRENDER)
{
const size_t captureLengthExt = (CAPTURELENGTH) ? dispInfo.customWidth : dispInfo.customWidth / 2;
const size_t captureLineCount = _gpuDstLineCount[l];
@ -4532,7 +4518,7 @@ void GPUEngineA::_RenderLine_DisplayCapture(u16 *dstColorLine, const u16 l)
{
case 0: // Capture VRAM
{
if (vramUsageProperty.isBlockUsed[vramReadBlock])
if (vramUsageProperty.isCustomBlockUsed[vramReadBlock])
{
this->_RenderLine_DispCapture_Copy<0, CAPTURELENGTH, false, false>(srcB, cap_dst_ext, captureLengthExt, captureLineCount);
}
@ -4547,13 +4533,12 @@ void GPUEngineA::_RenderLine_DisplayCapture(u16 *dstColorLine, const u16 l)
this->_RenderLine_DispCapture_Copy<1, CAPTURELENGTH, true, false>(srcB, cap_dst_ext, captureLengthExt, captureLineCount);
break;
}
break;
}
default: // Capture source is SourceA+B blended
{
if (vramUsageProperty.isBlockUsed[vramReadBlock])
if ( (DISPCAPCNT.SrcB == 0) && vramUsageProperty.isCustomBlockUsed[vramReadBlock] )
{
this->_RenderLine_DispCapture_Blend<CAPTURELENGTH, false, false, false>(srcA, srcB, cap_dst_ext, captureLengthExt, captureLineCount);
}
@ -4561,7 +4546,6 @@ void GPUEngineA::_RenderLine_DisplayCapture(u16 *dstColorLine, const u16 l)
{
this->_RenderLine_DispCapture_Blend<CAPTURELENGTH, false, true, false>(srcA, srcB, cap_dst_ext, captureLengthExt, captureLineCount);
}
break;
}
}
@ -4893,10 +4877,16 @@ void GPUEngineA::_HandleDisplayModeVRAM(u16 *__restrict dstColorLine, const size
}
else
{
// TODO: Get rid of this method's dependence on _engineMain->isCustomRenderingNeeded.
//
// The reason we need to check this on a per line basis instead of figuring this out at
// GPUSubsystem::UpdateRenderProperties() is because GPUSubsystem::UpdateRenderProperties()
// is called at line 0, but some games, such as Nanostray 2, might change DISPCNT in the
// middle of the frame render. (Nanostray 2 can change DISPCNT at line 1.)
const IOREG_DISPCNT &DISPCNT = this->_IORegisterMap->DISPCNT;
const VRAM3DUsageProperties &vramUsageProperty = GPU->GetVRAM3DUsageProperties();
const VRAM3DUsageProperties &vramUsageProperty = GPU->GetRenderProperties();
if (vramUsageProperty.isBlockUsed[DISPCNT.VRAM_Block] && (vramUsageProperty.blockIndexDisplayVRAM == DISPCNT.VRAM_Block))
if (vramUsageProperty.isCustomBlockUsed[DISPCNT.VRAM_Block])
{
const u16 *__restrict src = this->_VRAMaddrCustom + (_gpuDstLineIndex[l] * dstLineWidth);
#ifdef LOCAL_LE
@ -4930,9 +4920,10 @@ void GPUEngineA::_HandleDisplayModeVRAM(u16 *__restrict dstColorLine, const size
}
}
template<bool ISCUSTOMRENDERINGNEEDED>
void GPUEngineA::_HandleDisplayModeMainMemory(u16 *dstColorLine, const size_t l, const size_t dstLineWidth, const size_t dstLineCount)
void GPUEngineA::_HandleDisplayModeMainMemory(u16 *dstColorLine)
{
// Native rendering only.
//
//this has not been tested since the dma timing for dispfifo was changed around the time of
//newemuloop. it may not work.
@ -4950,21 +4941,6 @@ void GPUEngineA::_HandleDisplayModeMainMemory(u16 *dstColorLine, const size_t l,
((u32 *)dstColorLine)[i] = DISP_FIFOrecv() & 0x7FFF7FFF;
}
#endif
if (ISCUSTOMRENDERINGNEEDED)
{
for (size_t i = GPU_FRAMEBUFFER_NATIVE_WIDTH - 1; i < GPU_FRAMEBUFFER_NATIVE_WIDTH; i--)
{
for (size_t p = _gpuDstPitchCount[i] - 1; p < _gpuDstPitchCount[i]; p--)
{
dstColorLine[_gpuDstPitchIndex[i] + p] = dstColorLine[i];
}
}
for (size_t line = 1; line < dstLineCount; line++)
{
memcpy(dstColorLine + (line * dstLineWidth), dstColorLine, dstLineWidth * sizeof(u16));
}
}
}
template<GPULayerID LAYERID, bool ISDEBUGRENDER, bool MOSAIC, bool NOWINDOWSENABLEDHINT, bool COLOREFFECTDISABLEDHINT, bool ISCUSTOMRENDERINGNEEDED>
@ -5065,12 +5041,6 @@ void GPUEngineB::Reset()
template<bool ISCUSTOMRENDERINGNEEDED>
void GPUEngineB::RenderLine(const u16 l)
{
const NDSDisplayInfo &dispInfo = GPU->GetDisplayInfo();
const size_t dstLineWidth = (ISCUSTOMRENDERINGNEEDED) ? dispInfo.customWidth : GPU_FRAMEBUFFER_NATIVE_WIDTH;
const size_t dstLineCount = (ISCUSTOMRENDERINGNEEDED) ? _gpuDstLineCount[l] : 1;
const size_t dstLineIndex = (ISCUSTOMRENDERINGNEEDED) ? _gpuDstLineIndex[l] : l;
u16 *dstColorLine = (ISCUSTOMRENDERINGNEEDED) ? this->customBuffer + (dstLineIndex * dstLineWidth) : this->nativeBuffer + (dstLineIndex * dstLineWidth);
//cache some parameters which are assumed to be stable throughout the rendering of the entire line
if (this->_needUpdateWINH[0]) this->_UpdateWINH<0>();
if (this->_needUpdateWINH[1]) this->_UpdateWINH<1>();
@ -5082,13 +5052,21 @@ void GPUEngineB::RenderLine(const u16 l)
switch (displayMode)
{
case GPUDisplayMode_Off: // Display Off(Display white)
this->_HandleDisplayModeOff<ISCUSTOMRENDERINGNEEDED>(dstColorLine, l, dstLineWidth, dstLineCount);
this->_HandleDisplayModeOff(this->nativeBuffer + (l * GPU_FRAMEBUFFER_NATIVE_WIDTH));
break;
case GPUDisplayMode_Normal: // Display BG and OBJ layers
{
const NDSDisplayInfo &dispInfo = GPU->GetDisplayInfo();
const size_t dstLineWidth = (ISCUSTOMRENDERINGNEEDED) ? dispInfo.customWidth : GPU_FRAMEBUFFER_NATIVE_WIDTH;
const size_t dstLineCount = (ISCUSTOMRENDERINGNEEDED) ? _gpuDstLineCount[l] : 1;
const size_t dstLineIndex = (ISCUSTOMRENDERINGNEEDED) ? _gpuDstLineIndex[l] : l;
u16 *dstColorLine = (ISCUSTOMRENDERINGNEEDED) ? this->customBuffer + (dstLineIndex * dstLineWidth) : this->nativeBuffer + (dstLineIndex * dstLineWidth);
this->_RenderLine_Layer<ISCUSTOMRENDERINGNEEDED>(l, dstColorLine, dstLineWidth, dstLineCount);
this->_HandleDisplayModeNormal<ISCUSTOMRENDERINGNEEDED>(dstColorLine, l, dstLineWidth, dstLineCount);
break;
}
default:
break;
@ -5333,23 +5311,19 @@ void GPUSubsystem::Reset()
this->_engineMain->Reset();
this->_engineSub->Reset();
this->_VRAM3DUsage.blockIndexDisplayVRAM = VRAM_NO_3D_USAGE;
this->_VRAM3DUsage.isBlockUsed[0] = false;
this->_VRAM3DUsage.isBlockUsed[1] = false;
this->_VRAM3DUsage.isBlockUsed[2] = false;
this->_VRAM3DUsage.isBlockUsed[3] = false;
this->_VRAM3DUsage.isCustomBlockUsed[0] = false;
this->_VRAM3DUsage.isCustomBlockUsed[1] = false;
this->_VRAM3DUsage.isCustomBlockUsed[2] = false;
this->_VRAM3DUsage.isCustomBlockUsed[3] = false;
DISP_FIFOreset();
osd->clear();
}
void GPUSubsystem::UpdateVRAM3DUsageProperties()
void GPUSubsystem::UpdateRenderProperties()
{
const IOREG_DISPCNT &mainDISPCNT = this->_engineMain->GetIORegisterMap().DISPCNT;
this->_VRAM3DUsage.blockIndexDisplayVRAM = VRAM_NO_3D_USAGE;
this->_engineMain->isCustomRenderingNeeded = false;
this->_engineMain->isCustomOutputSize = false;
this->_engineMain->vramBlockBGIndex = VRAM_NO_3D_USAGE;
this->_engineMain->vramBlockOBJIndex = VRAM_NO_3D_USAGE;
this->_engineMain->vramBGLayer = VRAM_NO_3D_USAGE;
@ -5358,6 +5332,7 @@ void GPUSubsystem::UpdateVRAM3DUsageProperties()
this->_engineMain->renderedBuffer = this->_engineMain->nativeBuffer;
this->_engineSub->isCustomRenderingNeeded = false;
this->_engineSub->isCustomOutputSize = false;
this->_engineSub->vramBlockBGIndex = VRAM_NO_3D_USAGE;
this->_engineSub->vramBlockOBJIndex = VRAM_NO_3D_USAGE;
this->_engineSub->vramBGLayer = VRAM_NO_3D_USAGE;
@ -5383,12 +5358,12 @@ void GPUSubsystem::UpdateVRAM3DUsageProperties()
return;
}
this->_engineMain->isCustomRenderingNeeded = (mainDISPCNT.BG0_3D != 0);
this->_engineMain->isCustomRenderingNeeded = this->_engineMain->WillRender3DLayer();
// Iterate through VRAM banks A-D and determine if they will be used for this frame.
for (size_t i = 0; i < 4; i++)
{
if (!this->_VRAM3DUsage.isBlockUsed[i])
if (!this->_VRAM3DUsage.isCustomBlockUsed[i])
{
continue;
}
@ -5411,41 +5386,73 @@ void GPUSubsystem::UpdateVRAM3DUsageProperties()
this->_engineSub->UpdateVRAM3DUsageProperties_OBJLayer(i, this->_VRAM3DUsage);
break;
case VramConfiguration::LCDC:
{
if ((mainDISPCNT.DisplayMode == GPUDisplayMode_VRAM) && (mainDISPCNT.VRAM_Block == i))
{
this->_VRAM3DUsage.blockIndexDisplayVRAM = i;
}
default:
this->_VRAM3DUsage.isCustomBlockUsed[i] = false;
break;
}
}
this->_engineMain->isCustomRenderingNeeded = this->_engineMain->isCustomRenderingNeeded ||
(this->_engineMain->vramBlockBGIndex != VRAM_NO_3D_USAGE) ||
(this->_engineMain->vramBlockOBJIndex != VRAM_NO_3D_USAGE);
this->_engineSub->isCustomRenderingNeeded = (this->_engineSub->vramBlockBGIndex != VRAM_NO_3D_USAGE) ||
(this->_engineSub->vramBlockOBJIndex != VRAM_NO_3D_USAGE);
const GPUDisplayMode displayMode[2] = { (GPUDisplayMode)this->_engineMain->GetIORegisterMap().DISPCNT.DisplayMode,
(GPUDisplayMode)(this->_engineSub->GetIORegisterMap().DISPCNT.DisplayMode & 0x01) };
switch (displayMode[GPUEngineID_Main])
{
case GPUDisplayMode_Off:
case GPUDisplayMode_MainMemory:
this->_engineMain->isCustomOutputSize = false;
break;
case GPUDisplayMode_Normal:
this->_engineMain->isCustomOutputSize = this->_engineMain->isCustomRenderingNeeded;
break;
case GPUDisplayMode_VRAM:
// TODO: Get rid of this method's dependence on _engineMain->isCustomRenderingNeeded.
this->_engineMain->isCustomOutputSize = this->_engineMain->isCustomRenderingNeeded;
break;
}
switch (displayMode[GPUEngineID_Sub])
{
case GPUDisplayMode_Off:
this->_engineSub->isCustomOutputSize = false;
break;
case GPUDisplayMode_Normal:
this->_engineSub->isCustomOutputSize = this->_engineSub->isCustomRenderingNeeded;
break;
default:
this->_VRAM3DUsage.isBlockUsed[i] = false;
break;
}
}
if (this->_engineMain->isCustomRenderingNeeded)
if (this->_engineMain->isCustomOutputSize)
{
this->_engineMain->renderedWidth = this->_displayInfo.customWidth;
this->_engineMain->renderedHeight = this->_displayInfo.customHeight;
this->_engineMain->renderedBuffer = this->_engineMain->customBuffer;
}
if (this->_engineSub->isCustomRenderingNeeded)
if (this->_engineSub->isCustomOutputSize)
{
this->_engineSub->renderedWidth = this->_displayInfo.customWidth;
this->_engineSub->renderedHeight = this->_displayInfo.customHeight;
this->_engineSub->renderedBuffer = this->_engineSub->customBuffer;
}
this->_displayInfo.didPerformCustomRender[NDSDisplayID_Main] = this->_displayMain->GetEngine()->isCustomRenderingNeeded;
this->_displayInfo.didPerformCustomRender[NDSDisplayID_Main] = this->_displayMain->GetEngine()->isCustomOutputSize;
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_Touch] = this->_displayTouch->GetEngine()->isCustomRenderingNeeded;
this->_displayInfo.didPerformCustomRender[NDSDisplayID_Touch] = this->_displayTouch->GetEngine()->isCustomOutputSize;
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;
@ -5628,6 +5635,14 @@ void GPUSubsystem::SetCustomFramebufferSize(size_t w, size_t h, u16 *clientNativ
this->_displayInfo.customBuffer[NDSDisplayID_Main] = (this->_displayMain->GetEngine()->GetDisplayByID() == NDSDisplayID_Main) ? this->_displayInfo.masterCustomBuffer : this->_displayInfo.masterCustomBuffer + (w * h);
this->_displayInfo.customBuffer[NDSDisplayID_Touch] = (this->_displayTouch->GetEngine()->GetDisplayByID() == NDSDisplayID_Main) ? this->_displayInfo.masterCustomBuffer : this->_displayInfo.masterCustomBuffer + (w * h);
if (!this->_displayInfo.isCustomSizeRequested)
{
this->_VRAM3DUsage.isCustomBlockUsed[0] = false;
this->_VRAM3DUsage.isCustomBlockUsed[1] = false;
this->_VRAM3DUsage.isCustomBlockUsed[2] = false;
this->_VRAM3DUsage.isCustomBlockUsed[3] = false;
}
this->_engineMain->SetCustomFramebufferSize(w, h);
this->_engineSub->SetCustomFramebufferSize(w, h);
CurrentRenderer->SetFramebufferSize(w, h);
@ -5680,7 +5695,7 @@ u16* GPUSubsystem::GetCustomVRAMBlankBuffer()
return this->_customVRAMBlank;
}
VRAM3DUsageProperties& GPUSubsystem::GetVRAM3DUsageProperties()
VRAM3DUsageProperties& GPUSubsystem::GetRenderProperties()
{
return this->_VRAM3DUsage;
}
@ -5699,12 +5714,12 @@ void GPUSubsystem::RenderLine(const u16 l, bool isFrameSkipRequested)
{
if (l == 0)
{
CurrentRenderer->SetFramebufferFlushStates(this->_engineMain->Is3DRenderedLayerNeeded(), this->_engineMain->Is3DCapturingNeeded());
CurrentRenderer->SetFramebufferFlushStates(this->_engineMain->WillRender3DLayer(), this->_engineMain->WillCapture3DLayerDirect());
CurrentRenderer->RenderFinish();
CurrentRenderer->SetFramebufferFlushStates(true, true);
this->_event->DidFrameBegin();
this->UpdateVRAM3DUsageProperties();
this->UpdateRenderProperties();
// Clear displays to black if they are turned off by the user.
if (!isFrameSkipRequested)

View File

@ -1034,8 +1034,7 @@ struct DISPCAPCNT_parsed
typedef struct
{
u8 blockIndexDisplayVRAM;
bool isBlockUsed[4];
bool isCustomBlockUsed[4];
} VRAM3DUsageProperties;
typedef struct
@ -1079,6 +1078,7 @@ typedef struct
IOREG_BGnVOFS BGnVOFS;
BGLayerSize size;
BGType baseType;
BGType type;
u8 priority;
@ -1230,8 +1230,8 @@ protected:
template<bool ISCUSTOMRENDERINGNEEDED> void _RenderLine_Clear(const u16 clearColor, const u16 l, u16 *dstColorLine, const size_t dstLineWidth, const size_t dstLineCount);
template<bool ISCUSTOMRENDERINGNEEDED> void _RenderLine_Layer(const u16 l, u16 *dstColorLine, const size_t dstLineWidth, const size_t dstLineCount);
template<bool ISCUSTOMRENDERINGNEEDED> void _HandleDisplayModeOff(u16 *dstColorLine, const size_t l, const size_t dstLineWidth, const size_t dstLineCount);
template<bool ISCUSTOMRENDERINGNEEDED> void _HandleDisplayModeNormal(u16 *dstColorLine, const size_t l, const size_t dstLineWidth, const size_t dstLineCount);
void _HandleDisplayModeOff(u16 *dstColorLine);
template<bool ISCUSTOMOUTPUTSIZE> void _HandleDisplayModeNormal(u16 *dstColorLine, const size_t l, const size_t dstLineWidth, const size_t dstLineCount);
template<size_t WIN_NUM> void _UpdateWINH();
template<size_t WIN_NUM> void _SetupWindows(const u16 lineIndex);
@ -1307,6 +1307,7 @@ public:
void FramebufferPostprocess();
bool isCustomRenderingNeeded;
bool isCustomOutputSize;
u8 vramBGLayer;
u8 vramBlockBGIndex;
u8 vramBlockOBJIndex;
@ -1372,7 +1373,7 @@ protected:
template<GPULayerID LAYERID, bool ISDEBUGRENDER, bool MOSAIC, bool NOWINDOWSENABLEDHINT, bool COLOREFFECTDISABLEDHINT, bool ISCUSTOMRENDERINGNEEDED> void _LineLarge8bpp(u16 *__restrict dstColorLine, const u16 lineIndex);
template<bool ISCUSTOMRENDERINGNEEDED> void _RenderLine_Layer(const u16 l, u16 *dstColorLine, const size_t dstLineWidth, const size_t dstLineCount);
template<bool ISCUSTOMRENDERINGNEEDED, size_t CAPTURELENGTH> void _RenderLine_DisplayCapture(u16 *dstColorLine, const u16 l);
template<bool DIDCUSTOMRENDER, size_t CAPTURELENGTH> void _RenderLine_DisplayCapture(u16 *dstColorLine, const u16 l);
void _RenderLine_DispCapture_FIFOToBuffer(u16 *fifoLineBuffer);
template<int SOURCESWITCH, size_t CAPTURELENGTH, bool CAPTUREFROMNATIVESRC, bool CAPTURETONATIVEDST>
@ -1391,7 +1392,7 @@ protected:
void _RenderLine_DispCapture_Blend(const u16 *__restrict srcA, const u16 *__restrict srcB, u16 *__restrict dst, const size_t captureLengthExt, const size_t l);
template<bool ISCUSTOMRENDERINGNEEDED> void _HandleDisplayModeVRAM(u16 *__restrict dstColorLine, const size_t l, const size_t dstLineWidth, const size_t dstLineCount);
template<bool ISCUSTOMRENDERINGNEEDED> void _HandleDisplayModeMainMemory(u16 *dstColorLine, const size_t l, const size_t dstLineWidth, const size_t dstLineCount);
void _HandleDisplayModeMainMemory(u16 *dstColorLine);
public:
static GPUEngineA* Allocate();
@ -1404,8 +1405,8 @@ public:
u16* Get3DFramebufferRGBA5551() const;
virtual void SetCustomFramebufferSize(size_t w, size_t h);
bool Is3DRenderedLayerNeeded();
bool Is3DCapturingNeeded();
bool WillRender3DLayer();
bool WillCapture3DLayerDirect();
template<bool ISCUSTOMRENDERINGNEEDED> void RenderLine(const u16 l);
void FramebufferPostprocess();
@ -1499,7 +1500,7 @@ public:
GPUEventHandler* GetEventHandler();
void Reset();
VRAM3DUsageProperties& GetVRAM3DUsageProperties();
VRAM3DUsageProperties& GetRenderProperties();
const NDSDisplayInfo& GetDisplayInfo(); // Frontends need to call this whenever they need to read the video buffers from the emulator core
void SetDisplayDidCustomRender(NDSDisplayID displayID, bool theState);
@ -1516,7 +1517,7 @@ public:
void SetCustomFramebufferSize(size_t w, size_t h, u16 *clientNativeBuffer, u16 *clientCustomBuffer);
void SetCustomFramebufferSize(size_t w, size_t h);
void UpdateVRAM3DUsageProperties();
void UpdateRenderProperties();
// 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