split framebuffer.

setup doublebuffering inside GPU.cpp.
avoid copying a whole framebuffer every frame. better performance at higher res.
This commit is contained in:
Arisotura 2019-05-12 15:01:40 +02:00
parent 939a376389
commit c88981b589
4 changed files with 91 additions and 37 deletions

View File

@ -71,9 +71,9 @@ u32 VRAMMap_TexPal[8];
u32 VRAMMap_ARM7[2]; u32 VRAMMap_ARM7[2];
u32* Framebuffer; int FrontBuffer;
int FBScale; u32* Framebuffer[2][2];
int FBScreenStride; int FBScale[2];
GPU2D* GPU2D_A; GPU2D* GPU2D_A;
GPU2D* GPU2D_B; GPU2D* GPU2D_B;
@ -85,8 +85,12 @@ bool Init()
GPU2D_B = new GPU2D(1); GPU2D_B = new GPU2D(1);
if (!GPU3D::Init()) return false; if (!GPU3D::Init()) return false;
FrontBuffer = 0;
Framebuffer[0][0] = NULL; Framebuffer[0][1] = NULL;
Framebuffer[1][0] = NULL; Framebuffer[1][1] = NULL;
FBScale[0] = -1; FBScale[1] = -1;
//SetFramebufferScale(1); //SetFramebufferScale(1);
SetFramebufferScale(2); SetFramebufferScale(1, 1);
return true; return true;
} }
@ -97,7 +101,10 @@ void DeInit()
delete GPU2D_B; delete GPU2D_B;
GPU3D::DeInit(); GPU3D::DeInit();
if (Framebuffer) delete[] Framebuffer; if (Framebuffer[0][0]) delete[] Framebuffer[0][0];
if (Framebuffer[0][1]) delete[] Framebuffer[0][1];
if (Framebuffer[1][0]) delete[] Framebuffer[1][0];
if (Framebuffer[1][1]) delete[] Framebuffer[1][1];
} }
void Reset() void Reset()
@ -145,22 +152,32 @@ void Reset()
VRAMMap_ARM7[0] = 0; VRAMMap_ARM7[0] = 0;
VRAMMap_ARM7[1] = 0; VRAMMap_ARM7[1] = 0;
for (int i = 0; i < 256*192*2; i++) for (int i = 0; i < (256*192)<<(FBScale[0]*2); i++)
{ {
Framebuffer[i] = 0xFFFFFFFF; Framebuffer[0][0][i] = 0xFFFFFFFF;
Framebuffer[1][0][i] = 0xFFFFFFFF;
}
for (int i = 0; i < (256*192)<<(FBScale[1]*2); i++)
{
Framebuffer[0][1][i] = 0xFFFFFFFF;
Framebuffer[1][1][i] = 0xFFFFFFFF;
} }
GPU2D_A->Reset(); GPU2D_A->Reset();
GPU2D_B->Reset(); GPU2D_B->Reset();
GPU3D::Reset(); GPU3D::Reset();
GPU2D_A->SetFramebuffer(&Framebuffer[FBScreenStride]); int backbuf = FrontBuffer ? 0 : 1;
GPU2D_B->SetFramebuffer(&Framebuffer[0]); GPU2D_A->SetFramebuffer(Framebuffer[backbuf][1]);
GPU2D_B->SetFramebuffer(Framebuffer[backbuf][0]);
} }
void Stop() void Stop()
{ {
memset(Framebuffer, 0, FBScreenStride*2*sizeof(u32)); memset(Framebuffer[0][0], 0, (256*192)<<(FBScale[0]*2));
memset(Framebuffer[0][1], 0, (256*192)<<(FBScale[1]*2));
memset(Framebuffer[1][0], 0, (256*192)<<(FBScale[0]*2));
memset(Framebuffer[1][1], 0, (256*192)<<(FBScale[1]*2));
} }
void DoSavestate(Savestate* file) void DoSavestate(Savestate* file)
@ -215,13 +232,46 @@ void DoSavestate(Savestate* file)
GPU3D::DoSavestate(file); GPU3D::DoSavestate(file);
} }
void SetFramebufferScale(int scale) void AssignFramebuffers()
{ {
FBScale = scale; int backbuf = FrontBuffer ? 0 : 1;
FBScreenStride = (256*scale) * (192*scale); if (NDS::PowerControl9 & (1<<15))
{
GPU2D_A->SetFramebuffer(Framebuffer[backbuf][0]);
GPU2D_B->SetFramebuffer(Framebuffer[backbuf][1]);
}
else
{
GPU2D_A->SetFramebuffer(Framebuffer[backbuf][1]);
GPU2D_B->SetFramebuffer(Framebuffer[backbuf][0]);
}
}
if (Framebuffer) delete[] Framebuffer; void SetFramebufferScale(int top, int bottom)
Framebuffer = new u32[FBScreenStride * 2]; {
if (top != FBScale[0])
{
FBScale[0] = top;
int fbsize = (256 * 192) << (FBScale[0] * 2);
if (Framebuffer[0][0]) delete[] Framebuffer[0][0];
if (Framebuffer[1][0]) delete[] Framebuffer[1][0];
Framebuffer[0][0] = new u32[fbsize];
Framebuffer[1][0] = new u32[fbsize];
}
if (bottom != FBScale[1])
{
FBScale[1] = bottom;
int fbsize = (256 * 192) << (FBScale[1] * 2);
if (Framebuffer[0][1]) delete[] Framebuffer[0][1];
if (Framebuffer[1][1]) delete[] Framebuffer[1][1];
Framebuffer[0][1] = new u32[fbsize];
Framebuffer[1][1] = new u32[fbsize];
}
AssignFramebuffers();
} }
@ -682,16 +732,7 @@ void SetPowerCnt(u32 val)
GPU2D_B->SetEnabled(val & (1<<9)); GPU2D_B->SetEnabled(val & (1<<9));
GPU3D::SetEnabled(val & (1<<3), val & (1<<2)); GPU3D::SetEnabled(val & (1<<3), val & (1<<2));
if (val & (1<<15)) AssignFramebuffers();
{
GPU2D_A->SetFramebuffer(&Framebuffer[0]);
GPU2D_B->SetFramebuffer(&Framebuffer[FBScreenStride]);
}
else
{
GPU2D_A->SetFramebuffer(&Framebuffer[FBScreenStride]);
GPU2D_B->SetFramebuffer(&Framebuffer[0]);
}
} }
@ -762,6 +803,9 @@ void StartHBlank(u32 line)
void FinishFrame(u32 lines) void FinishFrame(u32 lines)
{ {
FrontBuffer = FrontBuffer ? 0 : 1;
AssignFramebuffers();
TotalScanlines = lines; TotalScanlines = lines;
} }

View File

@ -61,7 +61,8 @@ extern u32 VRAMMap_Texture[4];
extern u32 VRAMMap_TexPal[8]; extern u32 VRAMMap_TexPal[8];
extern u32 VRAMMap_ARM7[2]; extern u32 VRAMMap_ARM7[2];
extern u32* Framebuffer; extern int FrontBuffer;
extern u32* Framebuffer[2][2];
extern GPU2D* GPU2D_A; extern GPU2D* GPU2D_A;
extern GPU2D* GPU2D_B; extern GPU2D* GPU2D_B;
@ -74,7 +75,7 @@ void Stop();
void DoSavestate(Savestate* file); void DoSavestate(Savestate* file);
void SetFramebufferScale(int scale); void SetFramebufferScale(int top, int bottom);
void MapVRAM_AB(u32 bank, u8 cnt); void MapVRAM_AB(u32 bank, u8 cnt);

View File

@ -160,7 +160,7 @@ void Open()
uiRadioButtons* rbApplyScalingTo = uiNewRadioButtons(); uiRadioButtons* rbApplyScalingTo = uiNewRadioButtons();
uiRadioButtonsAppend(rbApplyScalingTo, "Both screens"); uiRadioButtonsAppend(rbApplyScalingTo, "Both screens");
uiRadioButtonsAppend(rbApplyScalingTo, "Emphasized screen"); uiRadioButtonsAppend(rbApplyScalingTo, "Emphasized screen (see 'Screen sizing')");
uiRadioButtonsAppend(rbApplyScalingTo, "Top screen"); uiRadioButtonsAppend(rbApplyScalingTo, "Top screen");
uiRadioButtonsAppend(rbApplyScalingTo, "Bottom screen"); uiRadioButtonsAppend(rbApplyScalingTo, "Bottom screen");
uiBoxAppend(in_ctrl, uiControl(rbApplyScalingTo), 0); uiBoxAppend(in_ctrl, uiControl(rbApplyScalingTo), 0);

View File

@ -95,7 +95,8 @@ char PrevSRAMPath[1024]; // for savestate 'undo load'
bool SavestateLoaded; bool SavestateLoaded;
bool ScreenDrawInited = false; bool ScreenDrawInited = false;
uiDrawBitmap* ScreenBitmap = NULL; uiDrawBitmap* ScreenBitmap[2] = {NULL,NULL};
SDL_mutex* ScreenMutex;
u32* ScreenBuffer; u32* ScreenBuffer;
int ScreenScale; int ScreenScale;
@ -555,7 +556,7 @@ int EmuThreadFunc(void* burp)
} }
} }
memcpy(ScreenBuffer, GPU::Framebuffer, (256*ScreenScale)*(384*ScreenScale)*4); //memcpy(ScreenBuffer, GPU::Framebuffer, (256*ScreenScale)*(384*ScreenScale)*4);
uiAreaQueueRedrawAll(MainDrawArea); uiAreaQueueRedrawAll(MainDrawArea);
// framerate limiter based off SDL2_gfx // framerate limiter based off SDL2_gfx
@ -636,24 +637,27 @@ void OnAreaDraw(uiAreaHandler* handler, uiArea* area, uiAreaDrawParams* params)
if (!ScreenDrawInited) if (!ScreenDrawInited)
{ {
ScreenDrawInited = true; ScreenDrawInited = true;
ScreenBitmap = uiDrawNewBitmap(params->Context, 256*ScreenScale, 384*ScreenScale); ScreenBitmap[0] = uiDrawNewBitmap(params->Context, 256*ScreenScale, 384*ScreenScale);
ScreenBitmap[1] = uiDrawNewBitmap(params->Context, 256*ScreenScale, 384*ScreenScale);
} }
if (!ScreenBitmap) return; if (!ScreenBitmap[0] || !ScreenBitmap[1]) return;
uiRect top = {0, 0, 256*ScreenScale, 192*ScreenScale}; uiRect top = {0, 0, 256*ScreenScale, 192*ScreenScale};
uiRect bot = {0, 192*ScreenScale, 256*ScreenScale, 192*ScreenScale}; uiRect bot = {0, 0, 256*ScreenScale, 192*ScreenScale};
if (ScreenBuffer) uiDrawBitmapUpdate(ScreenBitmap, ScreenBuffer); int frontbuf = GPU::FrontBuffer;
uiDrawBitmapUpdate(ScreenBitmap[0], GPU::Framebuffer[frontbuf][0]);
uiDrawBitmapUpdate(ScreenBitmap[1], GPU::Framebuffer[frontbuf][1]);
uiDrawSave(params->Context); uiDrawSave(params->Context);
uiDrawTransform(params->Context, &TopScreenTrans); uiDrawTransform(params->Context, &TopScreenTrans);
uiDrawBitmapDraw(params->Context, ScreenBitmap, &top, &TopScreenRect, Config::ScreenFilter==1); uiDrawBitmapDraw(params->Context, ScreenBitmap[0], &top, &TopScreenRect, Config::ScreenFilter==1);
uiDrawRestore(params->Context); uiDrawRestore(params->Context);
uiDrawSave(params->Context); uiDrawSave(params->Context);
uiDrawTransform(params->Context, &BottomScreenTrans); uiDrawTransform(params->Context, &BottomScreenTrans);
uiDrawBitmapDraw(params->Context, ScreenBitmap, &bot, &BottomScreenRect, Config::ScreenFilter==1); uiDrawBitmapDraw(params->Context, ScreenBitmap[1], &bot, &BottomScreenRect, Config::ScreenFilter==1);
uiDrawRestore(params->Context); uiDrawRestore(params->Context);
} }
@ -1993,6 +1997,8 @@ int main(int argc, char** argv)
uiMenuItemDisable(MenuItem_Reset); uiMenuItemDisable(MenuItem_Reset);
uiMenuItemDisable(MenuItem_Stop); uiMenuItemDisable(MenuItem_Stop);
ScreenMutex = SDL_CreateMutex();
uiAreaHandler areahandler; uiAreaHandler areahandler;
areahandler.Draw = OnAreaDraw; areahandler.Draw = OnAreaDraw;
areahandler.MouseEvent = OnAreaMouseEvent; areahandler.MouseEvent = OnAreaMouseEvent;
@ -2131,7 +2137,10 @@ int main(int argc, char** argv)
Config::Save(); Config::Save();
if (ScreenBitmap) uiDrawFreeBitmap(ScreenBitmap); SDL_DestroyMutex(ScreenMutex);
if (ScreenBitmap[0]) uiDrawFreeBitmap(ScreenBitmap[0]);
if (ScreenBitmap[1]) uiDrawFreeBitmap(ScreenBitmap[1]);
uiUninit(); uiUninit();
SDL_Quit(); SDL_Quit();