- 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_BG2].size = GPUEngineBase::_BGLayerSizeLUT[BGType_Affine][1];
this->_BGLayer[GPULayerID_BG3].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_BG0].type = BGType_Invalid;
this->_BGLayer[GPULayerID_BG1].type = BGType_Invalid; this->_BGLayer[GPULayerID_BG1].type = BGType_Invalid;
this->_BGLayer[GPULayerID_BG2].type = BGType_Invalid; this->_BGLayer[GPULayerID_BG2].type = BGType_Invalid;
@ -406,6 +411,7 @@ void GPUEngineBase::_Reset_Base()
this->_needUpdateWINH[1] = true; this->_needUpdateWINH[1] = true;
this->isCustomRenderingNeeded = false; this->isCustomRenderingNeeded = false;
this->isCustomOutputSize = false;
this->vramBGLayer = VRAM_NO_3D_USAGE; this->vramBGLayer = VRAM_NO_3D_USAGE;
this->vramBlockBGIndex = VRAM_NO_3D_USAGE; this->vramBlockBGIndex = VRAM_NO_3D_USAGE;
this->vramBlockOBJIndex = VRAM_NO_3D_USAGE; this->vramBlockOBJIndex = VRAM_NO_3D_USAGE;
@ -778,6 +784,8 @@ void GPUEngineBase::ParseReg_BGnCNT()
//clarify affine ext modes //clarify affine ext modes
BGType mode = GPUEngineBase::_mode2type[DISPCNT.BG_Mode][LAYERID]; BGType mode = GPUEngineBase::_mode2type[DISPCNT.BG_Mode][LAYERID];
this->_BGLayer[LAYERID].baseType = mode;
if (mode == BGType_AffineExt) if (mode == BGType_AffineExt)
{ {
//see: http://nocash.emubase.de/gbatek.htm#dsvideobgmodescontrol //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) void GPUEngineBase::UpdateVRAM3DUsageProperties_BGLayer(const size_t bankIndex, VRAM3DUsageProperties &outProperty)
{ {
const IOREG_DISPCNT &DISPCNT = this->_IORegisterMap->DISPCNT; 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 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 = 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);
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);
u8 selectedBGLayer = VRAM_NO_3D_USAGE; u8 selectedBGLayer = VRAM_NO_3D_USAGE;
if (!isBG2UsingVRAM && !isBG3UsingVRAM) if (!isBG2UsingVRAM && !isBG3UsingVRAM)
@ -3530,15 +3537,15 @@ void GPUEngineBase::UpdateVRAM3DUsageProperties_BGLayer(const size_t bankIndex,
} }
else if (!isBG2UsingVRAM && isBG3UsingVRAM) 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) 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) 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) if (selectedBGLayer != VRAM_NO_3D_USAGE)
@ -3559,14 +3566,13 @@ void GPUEngineBase::UpdateVRAM3DUsageProperties_BGLayer(const size_t bankIndex,
} }
this->vramBGLayer = selectedBGLayer; this->vramBGLayer = selectedBGLayer;
this->vramBlockBGIndex = bankIndex; this->vramBlockBGIndex = (selectedBGLayer != VRAM_NO_3D_USAGE) ? bankIndex : VRAM_NO_3D_USAGE;
this->isCustomRenderingNeeded = (selectedBGLayer != VRAM_NO_3D_USAGE);
} }
void GPUEngineBase::UpdateVRAM3DUsageProperties_OBJLayer(const size_t bankIndex, VRAM3DUsageProperties &outProperty) void GPUEngineBase::UpdateVRAM3DUsageProperties_OBJLayer(const size_t bankIndex, VRAM3DUsageProperties &outProperty)
{ {
const IOREG_DISPCNT &DISPCNT = this->_IORegisterMap->DISPCNT; 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; 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) ) if( (vramAddress == (DISPCAPCNT.VRAMWriteOffset * ADDRESS_STEP_32KB)) && (sprSize.width == 64) && (sprSize.height == 64) )
{ {
this->vramBlockOBJIndex = bankIndex; this->vramBlockOBJIndex = bankIndex;
this->isCustomRenderingNeeded = true;
return; 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> template <GPULayerID LAYERID, bool ISDEBUGRENDER, bool MOSAIC, bool NOWINDOWSENABLEDHINT, bool COLOREFFECTDISABLEDHINT, bool ISCUSTOMRENDERINGNEEDED>
void GPUEngineBase::_RenderLine_LayerBG_Final(u16 *dstColorLine, const u16 lineIndex) void GPUEngineBase::_RenderLine_LayerBG_Final(u16 *dstColorLine, const u16 lineIndex)
{ {
const BGType bgType = GPUEngineBase::_mode2type[this->_IORegisterMap->DISPCNT.BG_Mode][LAYERID];
bool useCustomVRAM = false; 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_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; 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)
void GPUEngineBase::_HandleDisplayModeOff(u16 *dstColorLine, const size_t l, const size_t dstLineWidth, const size_t dstLineCount)
{ {
// Native rendering only.
// In this display mode, the display is cleared to white. // In this display mode, the display is cleared to white.
if (ISCUSTOMRENDERINGNEEDED) memset_u16_fast<GPU_FRAMEBUFFER_NATIVE_WIDTH>(dstColorLine, 0x7FFF);
{
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) 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 //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; const IOREG_DISPCAPCNT &DISPCAPCNT = this->_IORegisterMap->DISPCAPCNT;
return ( (DISPCAPCNT.CaptureEnable != 0) && (vramConfiguration.banks[DISPCAPCNT.VRAMWriteBlock].purpose == VramConfiguration::LCDC) && (DISPCAPCNT.SrcA != 0) ); 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) switch (displayMode)
{ {
case GPUDisplayMode_Off: // Display Off(Display white) case GPUDisplayMode_Off: // Display Off(Display white)
this->_HandleDisplayModeOff<ISCUSTOMRENDERINGNEEDED>(dstColorLine, l, dstLineWidth, dstLineCount); this->_HandleDisplayModeOff(dstColorLine);
break; break;
case GPUDisplayMode_Normal: // Display BG and OBJ layers case GPUDisplayMode_Normal: // Display BG and OBJ layers
@ -4143,7 +4140,7 @@ void GPUEngineA::RenderLine(const u16 l)
break; break;
case GPUDisplayMode_MainMemory: // Display memory FIFO case GPUDisplayMode_MainMemory: // Display memory FIFO
this->_HandleDisplayModeMainMemory<ISCUSTOMRENDERINGNEEDED>(dstColorLine, l, dstLineWidth, dstLineCount); this->_HandleDisplayModeMainMemory(dstColorLine);
break; break;
} }
@ -4212,13 +4209,7 @@ void GPUEngineA::_RenderLine_Layer(const u16 l, u16 *dstColorLine, const size_t
const GPULayerID layerID = (GPULayerID)item->BGs[i]; const GPULayerID layerID = (GPULayerID)item->BGs[i];
if (this->_enableLayer[layerID]) if (this->_enableLayer[layerID])
{ {
// When determining whether to render the BG0 layer as a 3D layer, we only need to if ( (layerID == GPULayerID_BG0) && this->WillRender3DLayer() )
// 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))
{ {
const FragmentColor *__restrict framebuffer3D = CurrentRenderer->GetFramebuffer(); const FragmentColor *__restrict framebuffer3D = CurrentRenderer->GetFramebuffer();
if (framebuffer3D == NULL) 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) void GPUEngineA::_RenderLine_DisplayCapture(u16 *dstColorLine, const u16 l)
{ {
assert( (CAPTURELENGTH == GPU_FRAMEBUFFER_NATIVE_WIDTH/2) || (CAPTURELENGTH == GPU_FRAMEBUFFER_NATIVE_WIDTH) ); 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 IOREG_DISPCAPCNT &DISPCAPCNT = this->_IORegisterMap->DISPCAPCNT;
const NDSDisplayInfo &dispInfo = GPU->GetDisplayInfo(); const NDSDisplayInfo &dispInfo = GPU->GetDisplayInfo();
VRAM3DUsageProperties &vramUsageProperty = GPU->GetVRAM3DUsageProperties(); VRAM3DUsageProperties &vramUsageProperty = GPU->GetRenderProperties();
const u8 vramWriteBlock = DISPCAPCNT.VRAMWriteBlock; const u8 vramWriteBlock = DISPCAPCNT.VRAMWriteBlock;
const u8 vramReadBlock = DISPCNT.VRAM_Block; 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) case 0: // Capture screen (BG + OBJ + 3D)
{ {
//INFO("Capture screen (BG + OBJ + 3D)\n"); //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; break;
} }
case 1: // Capture 3D case 1: // Capture 3D
{ {
//INFO("Capture 3D\n"); //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; break;
} }
} }
vramUsageProperty.isBlockUsed[vramWriteBlock] = ISCUSTOMRENDERINGNEEDED; vramUsageProperty.isCustomBlockUsed[vramWriteBlock] = DIDCUSTOMRENDER;
break; break;
} }
@ -4429,16 +4420,16 @@ void GPUEngineA::_RenderLine_DisplayCapture(u16 *dstColorLine, const u16 l)
{ {
case 0: // Capture VRAM 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); this->_RenderLine_DispCapture_Copy<0, CAPTURELENGTH, false, true>(srcB, cap_dst, CAPTURELENGTH, 1);
vramUsageProperty.isCustomBlockUsed[vramWriteBlock] = true;
} }
else else
{ {
this->_RenderLine_DispCapture_Copy<0, CAPTURELENGTH, true, true>(srcB, cap_dst, CAPTURELENGTH, 1); this->_RenderLine_DispCapture_Copy<0, CAPTURELENGTH, true, true>(srcB, cap_dst, CAPTURELENGTH, 1);
vramUsageProperty.isCustomBlockUsed[vramWriteBlock] = false;
} }
vramUsageProperty.isBlockUsed[vramWriteBlock] = vramUsageProperty.isBlockUsed[vramReadBlock];
break; break;
} }
@ -4446,42 +4437,37 @@ void GPUEngineA::_RenderLine_DisplayCapture(u16 *dstColorLine, const u16 l)
{ {
this->_RenderLine_DispCapture_FIFOToBuffer(fifoLine); this->_RenderLine_DispCapture_FIFOToBuffer(fifoLine);
this->_RenderLine_DispCapture_Copy<1, CAPTURELENGTH, true, true>(srcB, cap_dst, CAPTURELENGTH, 1); this->_RenderLine_DispCapture_Copy<1, CAPTURELENGTH, true, true>(srcB, cap_dst, CAPTURELENGTH, 1);
vramUsageProperty.isBlockUsed[vramWriteBlock] = false; vramUsageProperty.isCustomBlockUsed[vramWriteBlock] = false;
break; break;
} }
} }
break; break;
} }
default: // Capture source is SourceA+B blended default: // Capture source is SourceA+B blended
{ {
//INFO("Capture source is SourceA+B blended\n"); //INFO("Capture source is SourceA+B blended\n");
if ( (DISPCAPCNT.SrcB == 0) && vramUsageProperty.isCustomBlockUsed[vramReadBlock] )
if (DISPCAPCNT.SrcB == 1)
{ {
// fifo - tested by splinter cell chaos theory thermal view this->_RenderLine_DispCapture_Blend<CAPTURELENGTH, !DIDCUSTOMRENDER, false, true>(srcA, srcB, cap_dst, CAPTURELENGTH, 1);
this->_RenderLine_DispCapture_FIFOToBuffer(fifoLine); vramUsageProperty.isCustomBlockUsed[vramWriteBlock] = true;
this->_RenderLine_DispCapture_Blend<CAPTURELENGTH, !ISCUSTOMRENDERINGNEEDED, true, true>(srcA, srcB, cap_dst, CAPTURELENGTH, 1);
} }
else else
{ {
if (vramUsageProperty.isBlockUsed[vramReadBlock]) if (DISPCAPCNT.SrcB != 0)
{ {
this->_RenderLine_DispCapture_Blend<CAPTURELENGTH, !ISCUSTOMRENDERINGNEEDED, false, true>(srcA, srcB, cap_dst, CAPTURELENGTH, 1); // fifo - tested by splinter cell chaos theory thermal view
} this->_RenderLine_DispCapture_FIFOToBuffer(fifoLine);
else
{
this->_RenderLine_DispCapture_Blend<CAPTURELENGTH, !ISCUSTOMRENDERINGNEEDED, true, true>(srcA, srcB, cap_dst, CAPTURELENGTH, 1);
} }
this->_RenderLine_DispCapture_Blend<CAPTURELENGTH, !DIDCUSTOMRENDER, true, true>(srcA, srcB, cap_dst, CAPTURELENGTH, 1);
vramUsageProperty.isCustomBlockUsed[vramWriteBlock] = DIDCUSTOMRENDER;
} }
vramUsageProperty.isBlockUsed[vramWriteBlock] = ISCUSTOMRENDERINGNEEDED || vramUsageProperty.isBlockUsed[vramReadBlock];
break; break;
} }
} }
if (ISCUSTOMRENDERINGNEEDED) if (DIDCUSTOMRENDER)
{ {
const size_t captureLengthExt = (CAPTURELENGTH) ? dispInfo.customWidth : dispInfo.customWidth / 2; const size_t captureLengthExt = (CAPTURELENGTH) ? dispInfo.customWidth : dispInfo.customWidth / 2;
const size_t captureLineCount = _gpuDstLineCount[l]; const size_t captureLineCount = _gpuDstLineCount[l];
@ -4532,7 +4518,7 @@ void GPUEngineA::_RenderLine_DisplayCapture(u16 *dstColorLine, const u16 l)
{ {
case 0: // Capture VRAM 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); 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); this->_RenderLine_DispCapture_Copy<1, CAPTURELENGTH, true, false>(srcB, cap_dst_ext, captureLengthExt, captureLineCount);
break; break;
} }
break; break;
} }
default: // Capture source is SourceA+B blended 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); 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); this->_RenderLine_DispCapture_Blend<CAPTURELENGTH, false, true, false>(srcA, srcB, cap_dst_ext, captureLengthExt, captureLineCount);
} }
break; break;
} }
} }
@ -4893,10 +4877,16 @@ void GPUEngineA::_HandleDisplayModeVRAM(u16 *__restrict dstColorLine, const size
} }
else 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 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); const u16 *__restrict src = this->_VRAMaddrCustom + (_gpuDstLineIndex[l] * dstLineWidth);
#ifdef LOCAL_LE #ifdef LOCAL_LE
@ -4930,9 +4920,10 @@ void GPUEngineA::_HandleDisplayModeVRAM(u16 *__restrict dstColorLine, const size
} }
} }
template<bool ISCUSTOMRENDERINGNEEDED> void GPUEngineA::_HandleDisplayModeMainMemory(u16 *dstColorLine)
void GPUEngineA::_HandleDisplayModeMainMemory(u16 *dstColorLine, const size_t l, const size_t dstLineWidth, const size_t dstLineCount)
{ {
// Native rendering only.
//
//this has not been tested since the dma timing for dispfifo was changed around the time of //this has not been tested since the dma timing for dispfifo was changed around the time of
//newemuloop. it may not work. //newemuloop. it may not work.
@ -4950,21 +4941,6 @@ void GPUEngineA::_HandleDisplayModeMainMemory(u16 *dstColorLine, const size_t l,
((u32 *)dstColorLine)[i] = DISP_FIFOrecv() & 0x7FFF7FFF; ((u32 *)dstColorLine)[i] = DISP_FIFOrecv() & 0x7FFF7FFF;
} }
#endif #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> template<GPULayerID LAYERID, bool ISDEBUGRENDER, bool MOSAIC, bool NOWINDOWSENABLEDHINT, bool COLOREFFECTDISABLEDHINT, bool ISCUSTOMRENDERINGNEEDED>
@ -5065,12 +5041,6 @@ void GPUEngineB::Reset()
template<bool ISCUSTOMRENDERINGNEEDED> template<bool ISCUSTOMRENDERINGNEEDED>
void GPUEngineB::RenderLine(const u16 l) 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 //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[0]) this->_UpdateWINH<0>();
if (this->_needUpdateWINH[1]) this->_UpdateWINH<1>(); if (this->_needUpdateWINH[1]) this->_UpdateWINH<1>();
@ -5082,14 +5052,22 @@ void GPUEngineB::RenderLine(const u16 l)
switch (displayMode) switch (displayMode)
{ {
case GPUDisplayMode_Off: // Display Off(Display white) case GPUDisplayMode_Off: // Display Off(Display white)
this->_HandleDisplayModeOff<ISCUSTOMRENDERINGNEEDED>(dstColorLine, l, dstLineWidth, dstLineCount); this->_HandleDisplayModeOff(this->nativeBuffer + (l * GPU_FRAMEBUFFER_NATIVE_WIDTH));
break; break;
case GPUDisplayMode_Normal: // Display BG and OBJ layers 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->_RenderLine_Layer<ISCUSTOMRENDERINGNEEDED>(l, dstColorLine, dstLineWidth, dstLineCount);
this->_HandleDisplayModeNormal<ISCUSTOMRENDERINGNEEDED>(dstColorLine, l, dstLineWidth, dstLineCount); this->_HandleDisplayModeNormal<ISCUSTOMRENDERINGNEEDED>(dstColorLine, l, dstLineWidth, dstLineCount);
break; break;
}
default: default:
break; break;
} }
@ -5333,23 +5311,19 @@ void GPUSubsystem::Reset()
this->_engineMain->Reset(); this->_engineMain->Reset();
this->_engineSub->Reset(); this->_engineSub->Reset();
this->_VRAM3DUsage.blockIndexDisplayVRAM = VRAM_NO_3D_USAGE; this->_VRAM3DUsage.isCustomBlockUsed[0] = false;
this->_VRAM3DUsage.isBlockUsed[0] = false; this->_VRAM3DUsage.isCustomBlockUsed[1] = false;
this->_VRAM3DUsage.isBlockUsed[1] = false; this->_VRAM3DUsage.isCustomBlockUsed[2] = false;
this->_VRAM3DUsage.isBlockUsed[2] = false; this->_VRAM3DUsage.isCustomBlockUsed[3] = false;
this->_VRAM3DUsage.isBlockUsed[3] = false;
DISP_FIFOreset(); DISP_FIFOreset();
osd->clear(); 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->isCustomRenderingNeeded = false;
this->_engineMain->isCustomOutputSize = false;
this->_engineMain->vramBlockBGIndex = VRAM_NO_3D_USAGE; this->_engineMain->vramBlockBGIndex = VRAM_NO_3D_USAGE;
this->_engineMain->vramBlockOBJIndex = VRAM_NO_3D_USAGE; this->_engineMain->vramBlockOBJIndex = VRAM_NO_3D_USAGE;
this->_engineMain->vramBGLayer = 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->_engineMain->renderedBuffer = this->_engineMain->nativeBuffer;
this->_engineSub->isCustomRenderingNeeded = false; this->_engineSub->isCustomRenderingNeeded = false;
this->_engineSub->isCustomOutputSize = false;
this->_engineSub->vramBlockBGIndex = VRAM_NO_3D_USAGE; this->_engineSub->vramBlockBGIndex = VRAM_NO_3D_USAGE;
this->_engineSub->vramBlockOBJIndex = VRAM_NO_3D_USAGE; this->_engineSub->vramBlockOBJIndex = VRAM_NO_3D_USAGE;
this->_engineSub->vramBGLayer = VRAM_NO_3D_USAGE; this->_engineSub->vramBGLayer = VRAM_NO_3D_USAGE;
@ -5383,12 +5358,12 @@ void GPUSubsystem::UpdateVRAM3DUsageProperties()
return; 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. // Iterate through VRAM banks A-D and determine if they will be used for this frame.
for (size_t i = 0; i < 4; i++) for (size_t i = 0; i < 4; i++)
{ {
if (!this->_VRAM3DUsage.isBlockUsed[i]) if (!this->_VRAM3DUsage.isCustomBlockUsed[i])
{ {
continue; continue;
} }
@ -5411,41 +5386,73 @@ void GPUSubsystem::UpdateVRAM3DUsageProperties()
this->_engineSub->UpdateVRAM3DUsageProperties_OBJLayer(i, this->_VRAM3DUsage); this->_engineSub->UpdateVRAM3DUsageProperties_OBJLayer(i, this->_VRAM3DUsage);
break; break;
case VramConfiguration::LCDC:
{
if ((mainDISPCNT.DisplayMode == GPUDisplayMode_VRAM) && (mainDISPCNT.VRAM_Block == i))
{
this->_VRAM3DUsage.blockIndexDisplayVRAM = i;
}
break;
}
default: default:
this->_VRAM3DUsage.isBlockUsed[i] = false; this->_VRAM3DUsage.isCustomBlockUsed[i] = false;
break; break;
} }
} }
if (this->_engineMain->isCustomRenderingNeeded) 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:
break;
}
if (this->_engineMain->isCustomOutputSize)
{ {
this->_engineMain->renderedWidth = this->_displayInfo.customWidth; this->_engineMain->renderedWidth = this->_displayInfo.customWidth;
this->_engineMain->renderedHeight = this->_displayInfo.customHeight; this->_engineMain->renderedHeight = this->_displayInfo.customHeight;
this->_engineMain->renderedBuffer = this->_engineMain->customBuffer; this->_engineMain->renderedBuffer = this->_engineMain->customBuffer;
} }
if (this->_engineSub->isCustomRenderingNeeded) if (this->_engineSub->isCustomOutputSize)
{ {
this->_engineSub->renderedWidth = this->_displayInfo.customWidth; this->_engineSub->renderedWidth = this->_displayInfo.customWidth;
this->_engineSub->renderedHeight = this->_displayInfo.customHeight; this->_engineSub->renderedHeight = this->_displayInfo.customHeight;
this->_engineSub->renderedBuffer = this->_engineSub->customBuffer; 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.renderedBuffer[NDSDisplayID_Main] = this->_displayMain->GetEngine()->renderedBuffer;
this->_displayInfo.renderedWidth[NDSDisplayID_Main] = this->_displayMain->GetEngine()->renderedWidth; this->_displayInfo.renderedWidth[NDSDisplayID_Main] = this->_displayMain->GetEngine()->renderedWidth;
this->_displayInfo.renderedHeight[NDSDisplayID_Main] = this->_displayMain->GetEngine()->renderedHeight; 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.renderedBuffer[NDSDisplayID_Touch] = this->_displayTouch->GetEngine()->renderedBuffer;
this->_displayInfo.renderedWidth[NDSDisplayID_Touch] = this->_displayTouch->GetEngine()->renderedWidth; this->_displayInfo.renderedWidth[NDSDisplayID_Touch] = this->_displayTouch->GetEngine()->renderedWidth;
this->_displayInfo.renderedHeight[NDSDisplayID_Touch] = this->_displayTouch->GetEngine()->renderedHeight; 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_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); 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->_engineMain->SetCustomFramebufferSize(w, h);
this->_engineSub->SetCustomFramebufferSize(w, h); this->_engineSub->SetCustomFramebufferSize(w, h);
CurrentRenderer->SetFramebufferSize(w, h); CurrentRenderer->SetFramebufferSize(w, h);
@ -5680,7 +5695,7 @@ u16* GPUSubsystem::GetCustomVRAMBlankBuffer()
return this->_customVRAMBlank; return this->_customVRAMBlank;
} }
VRAM3DUsageProperties& GPUSubsystem::GetVRAM3DUsageProperties() VRAM3DUsageProperties& GPUSubsystem::GetRenderProperties()
{ {
return this->_VRAM3DUsage; return this->_VRAM3DUsage;
} }
@ -5699,12 +5714,12 @@ void GPUSubsystem::RenderLine(const u16 l, bool isFrameSkipRequested)
{ {
if (l == 0) if (l == 0)
{ {
CurrentRenderer->SetFramebufferFlushStates(this->_engineMain->Is3DRenderedLayerNeeded(), this->_engineMain->Is3DCapturingNeeded()); CurrentRenderer->SetFramebufferFlushStates(this->_engineMain->WillRender3DLayer(), this->_engineMain->WillCapture3DLayerDirect());
CurrentRenderer->RenderFinish(); CurrentRenderer->RenderFinish();
CurrentRenderer->SetFramebufferFlushStates(true, true); CurrentRenderer->SetFramebufferFlushStates(true, true);
this->_event->DidFrameBegin(); this->_event->DidFrameBegin();
this->UpdateVRAM3DUsageProperties(); this->UpdateRenderProperties();
// Clear displays to black if they are turned off by the user. // Clear displays to black if they are turned off by the user.
if (!isFrameSkipRequested) if (!isFrameSkipRequested)

View File

@ -1034,8 +1034,7 @@ struct DISPCAPCNT_parsed
typedef struct typedef struct
{ {
u8 blockIndexDisplayVRAM; bool isCustomBlockUsed[4];
bool isBlockUsed[4];
} VRAM3DUsageProperties; } VRAM3DUsageProperties;
typedef struct typedef struct
@ -1079,6 +1078,7 @@ typedef struct
IOREG_BGnVOFS BGnVOFS; IOREG_BGnVOFS BGnVOFS;
BGLayerSize size; BGLayerSize size;
BGType baseType;
BGType type; BGType type;
u8 priority; 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_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 _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); void _HandleDisplayModeOff(u16 *dstColorLine);
template<bool ISCUSTOMRENDERINGNEEDED> void _HandleDisplayModeNormal(u16 *dstColorLine, const size_t l, const size_t dstLineWidth, const size_t dstLineCount); 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 _UpdateWINH();
template<size_t WIN_NUM> void _SetupWindows(const u16 lineIndex); template<size_t WIN_NUM> void _SetupWindows(const u16 lineIndex);
@ -1307,6 +1307,7 @@ public:
void FramebufferPostprocess(); void FramebufferPostprocess();
bool isCustomRenderingNeeded; bool isCustomRenderingNeeded;
bool isCustomOutputSize;
u8 vramBGLayer; u8 vramBGLayer;
u8 vramBlockBGIndex; u8 vramBlockBGIndex;
u8 vramBlockOBJIndex; 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<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> 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); void _RenderLine_DispCapture_FIFOToBuffer(u16 *fifoLineBuffer);
template<int SOURCESWITCH, size_t CAPTURELENGTH, bool CAPTUREFROMNATIVESRC, bool CAPTURETONATIVEDST> 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); 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 _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: public:
static GPUEngineA* Allocate(); static GPUEngineA* Allocate();
@ -1404,8 +1405,8 @@ public:
u16* Get3DFramebufferRGBA5551() const; u16* Get3DFramebufferRGBA5551() const;
virtual void SetCustomFramebufferSize(size_t w, size_t h); virtual void SetCustomFramebufferSize(size_t w, size_t h);
bool Is3DRenderedLayerNeeded(); bool WillRender3DLayer();
bool Is3DCapturingNeeded(); bool WillCapture3DLayerDirect();
template<bool ISCUSTOMRENDERINGNEEDED> void RenderLine(const u16 l); template<bool ISCUSTOMRENDERINGNEEDED> void RenderLine(const u16 l);
void FramebufferPostprocess(); void FramebufferPostprocess();
@ -1499,7 +1500,7 @@ public:
GPUEventHandler* GetEventHandler(); GPUEventHandler* GetEventHandler();
void Reset(); 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 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); 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, u16 *clientNativeBuffer, u16 *clientCustomBuffer);
void SetCustomFramebufferSize(size_t w, size_t h); void SetCustomFramebufferSize(size_t w, size_t h);
void UpdateVRAM3DUsageProperties(); void UpdateRenderProperties();
// Normally, the GPUs will automatically resolve their native buffers to the master // 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 // custom framebuffer at the end of V-blank so that all rendered graphics are contained