GPU: The output framebuffers are now double-buffered and page-aligned.

- Framebuffers are now page-aligned on 4KB boundaries. This is to
improve performance when using the framebuffers directly as pinned AGP
memory.
- Framebuffers are now double-buffered. The target buffer index is now
tracked using the bufferIndex field of NDSDisplayInfo.
- Clients may no longer supply their own buffers to
SetCustomFramebufferSize(). Clients must use the pointers supplied by
NDSDisplayInfo.
- The frameskip flag is now set only on line 0 and remains consistent
for all 192 lines of rendering.
- GPUSubsystem no longer needs a special allocater/deallocator for
itself, so it has been reverted back to a standard C++ new/delete.
- Add a GPUClientFetchObject helper class as an aid to clients that
need to read out the framebuffers. (Should probably move to its own
file at some later date.)
This commit is contained in:
rogerman 2017-02-01 09:34:21 -08:00
parent fc3570a18a
commit 08b8a1a62c
4 changed files with 284 additions and 155 deletions

View File

@ -2,7 +2,7 @@
Copyright (C) 2006 yopyop
Copyright (C) 2006-2007 Theo Berkau
Copyright (C) 2007 shash
Copyright (C) 2008-2016 DeSmuME team
Copyright (C) 2008-2017 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -4816,8 +4816,12 @@ void GPUEngineBase::SetDisplayByID(const NDSDisplayID theDisplayID)
{
const NDSDisplayInfo &dispInfo = GPU->GetDisplayInfo();
this->_targetDisplayID = theDisplayID;
this->nativeBuffer = dispInfo.nativeBuffer[theDisplayID];
this->customBuffer = dispInfo.customBuffer[theDisplayID];
const size_t nativeFramebufferSize = GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * dispInfo.pixelBytes;
const size_t customFramebufferSize = dispInfo.customWidth * dispInfo.customHeight * dispInfo.pixelBytes;
this->nativeBuffer = (theDisplayID == NDSDisplayID_Main) ? dispInfo.masterNativeBuffer : (u8 *)dispInfo.masterNativeBuffer + nativeFramebufferSize;
this->customBuffer = (theDisplayID == NDSDisplayID_Main) ? dispInfo.masterCustomBuffer : (u8 *)dispInfo.masterCustomBuffer + customFramebufferSize;
}
GPUEngineID GPUEngineBase::GetEngineID() const
@ -4841,11 +4845,19 @@ void GPUEngineBase::SetCustomFramebufferSize(size_t w, size_t h)
this->_internalRenderLineTargetCustom = newWorkingLineColor;
this->_renderLineLayerIDCustom = newWorkingLineLayerID;
this->nativeBuffer = GPU->GetDisplayInfo().nativeBuffer[this->_targetDisplayID];
this->customBuffer = GPU->GetDisplayInfo().customBuffer[this->_targetDisplayID];
this->_bgLayerIndexCustom = newBGLayerIndexCustom;
this->_bgLayerColorCustom = newBGLayerColorCustom;
const NDSDisplayInfo &dispInfo = GPU->GetDisplayInfo();
const size_t nativeFramebufferSize = GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * dispInfo.pixelBytes;
const size_t customFramebufferSize = w * h * dispInfo.pixelBytes;
this->nativeBuffer = (this->_targetDisplayID == NDSDisplayID_Main) ? dispInfo.masterNativeBuffer : (u8 *)dispInfo.masterNativeBuffer + nativeFramebufferSize;
this->customBuffer = (this->_targetDisplayID == NDSDisplayID_Main) ? dispInfo.masterCustomBuffer : (u8 *)dispInfo.masterCustomBuffer + customFramebufferSize;
this->renderedBuffer = this->nativeBuffer;
this->renderedWidth = GPU_FRAMEBUFFER_NATIVE_WIDTH;
this->renderedHeight = GPU_FRAMEBUFFER_NATIVE_HEIGHT;
this->_didPassWindowTestCustomMasterPtr = newDidPassWindowTestCustomMasterPtr;
this->_didPassWindowTestCustom[GPULayerID_BG0] = this->_didPassWindowTestCustomMasterPtr + (0 * w * sizeof(u8));
this->_didPassWindowTestCustom[GPULayerID_BG1] = this->_didPassWindowTestCustomMasterPtr + (1 * w * sizeof(u8));
@ -6772,6 +6784,7 @@ GPUSubsystem::GPUSubsystem()
_videoFrameCount = 0;
_render3DFrameCount = 0;
_frameNeedsFinish = false;
_willFrameSkip = false;
_willAutoApplyMasterBrightness = true;
_willAutoConvertRGB666ToRGB888 = true;
_willAutoResolveToCustomBuffer = true;
@ -6789,13 +6802,16 @@ GPUSubsystem::GPUSubsystem()
_customVRAM = NULL;
_customVRAMBlank = NULL;
_customFramebuffer = malloc_alignedCacheLine(GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2 * _displayInfo.pixelBytes);
_displayInfo.framebufferSize = ((GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT) + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT)) * 2 * _displayInfo.pixelBytes;
_masterFramebuffer = malloc_alignedPage(_displayInfo.framebufferSize * 2);
_displayInfo.masterNativeBuffer = _nativeFramebuffer;
_displayInfo.bufferIndex = 0;
_displayInfo.masterFramebufferHead = _masterFramebuffer;
_displayInfo.masterNativeBuffer = _masterFramebuffer;
_displayInfo.nativeBuffer[NDSDisplayID_Main] = _displayInfo.masterNativeBuffer;
_displayInfo.nativeBuffer[NDSDisplayID_Touch] = (u8 *)_displayInfo.masterNativeBuffer + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * _displayInfo.pixelBytes);
_displayInfo.masterCustomBuffer = _customFramebuffer;
_displayInfo.masterCustomBuffer = (u8 *)_masterFramebuffer + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2 * _displayInfo.pixelBytes);
_displayInfo.customBuffer[NDSDisplayID_Main] = _displayInfo.masterCustomBuffer;
_displayInfo.customBuffer[NDSDisplayID_Touch] = (u8 *)_displayInfo.masterCustomBuffer + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * _displayInfo.pixelBytes);
@ -6817,7 +6833,7 @@ GPUSubsystem::~GPUSubsystem()
//delete osd;
//osd = NULL;
free_aligned(this->_customFramebuffer);
free_aligned(this->_masterFramebuffer);
free_aligned(this->_customVRAM);
free_aligned(_gpuDstToSrcIndex);
@ -6840,17 +6856,6 @@ GPUSubsystem::~GPUSubsystem()
delete _defaultEventHandler;
}
GPUSubsystem* GPUSubsystem::Allocate()
{
return new(malloc_aligned64(sizeof(GPUSubsystem))) GPUSubsystem();
}
void GPUSubsystem::FinalizeAndDeallocate()
{
this->~GPUSubsystem();
free_aligned(this);
}
void GPUSubsystem::_UpdateFPSRender3D()
{
this->_videoFrameCount++;
@ -6879,6 +6884,7 @@ void GPUSubsystem::Reset()
this->SetCustomFramebufferSize(this->_displayInfo.customWidth, this->_displayInfo.customHeight);
}
this->_willFrameSkip = false;
this->_videoFrameCount = 0;
this->_render3DFrameCount = 0;
@ -6934,21 +6940,24 @@ void GPUSubsystem::ForceFrameStop()
if (this->_frameNeedsFinish)
{
this->_frameNeedsFinish = false;
this->_event->DidFrameEnd(false);
this->_event->DidFrameEnd(false, this->_displayInfo);
}
}
bool GPUSubsystem::GetWillFrameSkip() const
{
return this->_willFrameSkip;
}
void GPUSubsystem::SetWillFrameSkip(const bool willFrameSkip)
{
this->_willFrameSkip = willFrameSkip;
}
void GPUSubsystem::UpdateRenderProperties()
{
this->_engineMain->vramBlockOBJIndex = VRAM_NO_3D_USAGE;
this->_engineMain->renderedWidth = GPU_FRAMEBUFFER_NATIVE_WIDTH;
this->_engineMain->renderedHeight = GPU_FRAMEBUFFER_NATIVE_HEIGHT;
this->_engineMain->renderedBuffer = this->_engineMain->nativeBuffer;
this->_engineSub->vramBlockOBJIndex = VRAM_NO_3D_USAGE;
this->_engineSub->renderedWidth = GPU_FRAMEBUFFER_NATIVE_WIDTH;
this->_engineSub->renderedHeight = GPU_FRAMEBUFFER_NATIVE_HEIGHT;
this->_engineSub->renderedBuffer = this->_engineSub->nativeBuffer;
this->_engineMain->nativeLineRenderCount = GPU_FRAMEBUFFER_NATIVE_HEIGHT;
this->_engineMain->nativeLineOutputCount = GPU_FRAMEBUFFER_NATIVE_HEIGHT;
@ -6962,19 +6971,43 @@ void GPUSubsystem::UpdateRenderProperties()
this->_engineSub->isLineOutputNative[l] = true;
}
this->_displayInfo.bufferIndex = (this->_displayInfo.bufferIndex + 1) & 0x01;
const size_t nativeFramebufferSize = GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * this->_displayInfo.pixelBytes;
const size_t customFramebufferSize = this->_displayInfo.customWidth * this->_displayInfo.customHeight * this->_displayInfo.pixelBytes;
this->_displayInfo.masterNativeBuffer = (u8 *)this->_masterFramebuffer + (this->_displayInfo.bufferIndex * this->_displayInfo.framebufferSize);
this->_displayInfo.masterCustomBuffer = (u8 *)this->_masterFramebuffer + (nativeFramebufferSize * 2) + (this->_displayInfo.bufferIndex * this->_displayInfo.framebufferSize);
this->_engineMain->nativeBuffer = (this->_engineMain->GetDisplayByID() == NDSDisplayID_Main) ? this->_displayInfo.masterNativeBuffer : (u8 *)this->_displayInfo.masterNativeBuffer + nativeFramebufferSize;
this->_engineMain->customBuffer = (this->_engineMain->GetDisplayByID() == NDSDisplayID_Main) ? this->_displayInfo.masterCustomBuffer : (u8 *)this->_displayInfo.masterCustomBuffer + customFramebufferSize;
this->_engineMain->renderedBuffer = this->_engineMain->nativeBuffer;
this->_engineMain->renderedWidth = GPU_FRAMEBUFFER_NATIVE_WIDTH;
this->_engineMain->renderedHeight = GPU_FRAMEBUFFER_NATIVE_HEIGHT;
this->_engineSub->nativeBuffer = (this->_engineSub->GetDisplayByID() == NDSDisplayID_Main) ? this->_displayInfo.masterNativeBuffer : (u8 *)this->_displayInfo.masterNativeBuffer + nativeFramebufferSize;
this->_engineSub->customBuffer = (this->_engineSub->GetDisplayByID() == NDSDisplayID_Main) ? this->_displayInfo.masterCustomBuffer : (u8 *)this->_displayInfo.masterCustomBuffer + customFramebufferSize;
this->_engineSub->renderedBuffer = this->_engineSub->nativeBuffer;
this->_engineSub->renderedWidth = GPU_FRAMEBUFFER_NATIVE_WIDTH;
this->_engineSub->renderedHeight = GPU_FRAMEBUFFER_NATIVE_HEIGHT;
GPUEngineBase *mainEngine = this->_displayMain->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();
this->_displayInfo.nativeBuffer[NDSDisplayID_Touch] = touchEngine->nativeBuffer;
this->_displayInfo.customBuffer[NDSDisplayID_Touch] = touchEngine->customBuffer;
this->_displayInfo.renderedBuffer[NDSDisplayID_Touch] = touchEngine->renderedBuffer;
this->_displayInfo.renderedWidth[NDSDisplayID_Touch] = touchEngine->renderedWidth;
this->_displayInfo.renderedHeight[NDSDisplayID_Touch] = touchEngine->renderedHeight;
this->_displayInfo.didPerformCustomRender[NDSDisplayID_Main] = false;
this->_displayInfo.didPerformCustomRender[NDSDisplayID_Touch] = false;
this->_displayInfo.nativeBuffer[NDSDisplayID_Main] = this->_displayMain->GetEngine()->nativeBuffer;
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.nativeBuffer[NDSDisplayID_Touch] = this->_displayTouch->GetEngine()->nativeBuffer;
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;
if (!this->_displayInfo.isCustomSizeRequested)
{
return;
@ -7061,7 +7094,7 @@ size_t GPUSubsystem::GetCustomFramebufferHeight() const
return this->_displayInfo.customHeight;
}
void GPUSubsystem::SetCustomFramebufferSize(size_t w, size_t h, void *clientNativeBuffer, void *clientCustomBuffer)
void GPUSubsystem::SetCustomFramebufferSize(size_t w, size_t h)
{
if (w < GPU_FRAMEBUFFER_NATIVE_WIDTH || h < GPU_FRAMEBUFFER_NATIVE_HEIGHT)
{
@ -7193,7 +7226,7 @@ void GPUSubsystem::SetCustomFramebufferSize(size_t w, size_t h, void *clientNati
this->_displayInfo.renderedHeight[NDSDisplayID_Touch] = GPU_FRAMEBUFFER_NATIVE_HEIGHT;
}
this->_AllocateFramebuffers(this->_displayInfo.colorFormat, w, h, clientNativeBuffer, clientCustomBuffer);
this->_AllocateFramebuffers(this->_displayInfo.colorFormat, w, h);
free_aligned(oldGpuDstToSrcIndexPtr);
free_aligned(oldGpuDstToSrcSSSE3_u8_8e);
@ -7201,108 +7234,79 @@ void GPUSubsystem::SetCustomFramebufferSize(size_t w, size_t h, void *clientNati
free_aligned(oldGpuDstToSrcSSSE3_u16_8e);
}
void GPUSubsystem::SetCustomFramebufferSize(size_t w, size_t h)
{
this->SetCustomFramebufferSize(w, h, NULL, NULL);
}
void GPUSubsystem::SetColorFormat(const NDSColorFormat outputFormat, void *clientNativeBuffer, void *clientCustomBuffer)
void GPUSubsystem::SetColorFormat(const NDSColorFormat outputFormat)
{
this->_displayInfo.colorFormat = outputFormat;
this->_displayInfo.pixelBytes = (outputFormat == NDSColorFormat_BGR555_Rev) ? sizeof(u16) : sizeof(FragmentColor);
this->_AllocateFramebuffers(this->_displayInfo.colorFormat, this->_displayInfo.customWidth, this->_displayInfo.customHeight, clientNativeBuffer, clientCustomBuffer);
this->_AllocateFramebuffers(this->_displayInfo.colorFormat, this->_displayInfo.customWidth, this->_displayInfo.customHeight);
}
void GPUSubsystem::SetColorFormat(const NDSColorFormat outputFormat)
void GPUSubsystem::_AllocateFramebuffers(NDSColorFormat outputFormat, size_t w, size_t h)
{
this->SetColorFormat(outputFormat, NULL, NULL);
}
void GPUSubsystem::_AllocateFramebuffers(NDSColorFormat outputFormat, size_t w, size_t h, void *clientNativeBuffer, void *clientCustomBuffer)
{
void *oldCustomFramebuffer = this->_customFramebuffer;
void *oldMasterFramebuffer = this->_masterFramebuffer;
void *oldCustomVRAM = this->_customVRAM;
const size_t pixelBytes = (outputFormat == NDSColorFormat_BGR555_Rev) ? sizeof(u16) : sizeof(FragmentColor);
const size_t newCustomVRAMBlockSize = _gpuCaptureLineIndex[GPU_VRAM_BLOCK_LINES] * w;
const size_t newCustomVRAMBlankSize = _gpuLargestDstLineCount * GPU_VRAM_BLANK_REGION_LINES * w;
const size_t nativeFramebufferSize = GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2 * pixelBytes;
const size_t nativeFramebufferSize = GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * pixelBytes;
const size_t customFramebufferSize = w * h * pixelBytes;
u16 *newCustomVRAM = (u16 *)malloc_alignedCacheLine(((newCustomVRAMBlockSize * 4) + newCustomVRAMBlankSize) * pixelBytes);
memset(newCustomVRAM, 0, ((newCustomVRAMBlockSize * 4) + newCustomVRAMBlankSize) * pixelBytes);
this->_customVRAM = newCustomVRAM;
this->_customVRAMBlank = newCustomVRAM + (newCustomVRAMBlockSize * 4);
if (clientNativeBuffer != NULL)
{
if (this->_displayInfo.masterNativeBuffer != clientNativeBuffer)
{
memcpy(clientNativeBuffer, this->_displayInfo.masterNativeBuffer, nativeFramebufferSize);
}
this->_displayInfo.framebufferSize = (nativeFramebufferSize * 2) + (customFramebufferSize * 2);
this->_masterFramebuffer = malloc_alignedPage(this->_displayInfo.framebufferSize * 2);
this->_displayInfo.masterFramebufferHead = this->_masterFramebuffer;
this->_displayInfo.masterNativeBuffer = (u8 *)this->_masterFramebuffer + (this->_displayInfo.bufferIndex * this->_displayInfo.framebufferSize);
this->_displayInfo.masterCustomBuffer = (u8 *)this->_masterFramebuffer + (nativeFramebufferSize * 2) + (this->_displayInfo.bufferIndex * this->_displayInfo.framebufferSize);
this->_displayInfo.masterNativeBuffer = clientNativeBuffer;
}
else
{
if (this->_displayInfo.masterNativeBuffer != this->_nativeFramebuffer)
{
memcpy(this->_nativeFramebuffer, this->_displayInfo.masterNativeBuffer, nativeFramebufferSize);
}
this->_engineMain->SetCustomFramebufferSize(w, h);
this->_engineSub->SetCustomFramebufferSize(w, h);
this->_displayInfo.masterNativeBuffer = this->_nativeFramebuffer;
}
GPUEngineBase *mainEngine = this->_displayMain->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;
if (clientCustomBuffer != NULL)
{
this->_customFramebuffer = NULL;
this->_displayInfo.masterCustomBuffer = clientCustomBuffer;
}
else
{
void *newCustomFramebuffer = malloc_alignedCacheLine(w * h * 2 * pixelBytes);
this->_customFramebuffer = newCustomFramebuffer;
this->_displayInfo.masterCustomBuffer = newCustomFramebuffer;
}
GPUEngineBase *touchEngine = this->_displayTouch->GetEngine();
this->_displayInfo.nativeBuffer[NDSDisplayID_Touch] = touchEngine->nativeBuffer;
this->_displayInfo.customBuffer[NDSDisplayID_Touch] = touchEngine->customBuffer;
this->_displayInfo.renderedBuffer[NDSDisplayID_Touch] = touchEngine->renderedBuffer;
this->_displayInfo.renderedWidth[NDSDisplayID_Touch] = touchEngine->renderedWidth;
this->_displayInfo.renderedHeight[NDSDisplayID_Touch] = touchEngine->renderedHeight;
switch (outputFormat)
{
case NDSColorFormat_BGR555_Rev:
memset_u16(this->_displayInfo.masterCustomBuffer, 0x8000, w * h * 2);
memset_u16(this->_masterFramebuffer, 0x8000, (this->_displayInfo.framebufferSize * 2) / pixelBytes);
break;
case NDSColorFormat_BGR666_Rev:
memset_u32(this->_displayInfo.masterCustomBuffer, 0x1F000000, w * h * 2);
memset_u32(this->_masterFramebuffer, 0x1F000000, (this->_displayInfo.framebufferSize * 2) / pixelBytes);
break;
case NDSColorFormat_BGR888_Rev:
memset_u32(this->_displayInfo.masterCustomBuffer, 0xFF000000, w * h * 2);
memset_u32(this->_masterFramebuffer, 0xFF000000, (this->_displayInfo.framebufferSize * 2) / pixelBytes);
break;
default:
break;
}
this->_customVRAM = newCustomVRAM;
this->_customVRAMBlank = newCustomVRAM + (newCustomVRAMBlockSize * 4);
this->_displayInfo.nativeBuffer[NDSDisplayID_Main] = (this->_displayMain->GetEngine()->GetDisplayByID() == NDSDisplayID_Main) ? this->_displayInfo.masterNativeBuffer : (u8 *)this->_displayInfo.masterNativeBuffer + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * this->_displayInfo.pixelBytes);
this->_displayInfo.nativeBuffer[NDSDisplayID_Touch] = (this->_displayTouch->GetEngine()->GetDisplayByID() == NDSDisplayID_Main) ? this->_displayInfo.masterNativeBuffer : (u8 *)this->_displayInfo.masterNativeBuffer + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * this->_displayInfo.pixelBytes);
this->_displayInfo.customBuffer[NDSDisplayID_Main] = (this->_displayMain->GetEngine()->GetDisplayByID() == NDSDisplayID_Main) ? this->_displayInfo.masterCustomBuffer : (u8 *)this->_displayInfo.masterCustomBuffer + (w * h * this->_displayInfo.pixelBytes);
this->_displayInfo.customBuffer[NDSDisplayID_Touch] = (this->_displayTouch->GetEngine()->GetDisplayByID() == NDSDisplayID_Main) ? this->_displayInfo.masterCustomBuffer : (u8 *)this->_displayInfo.masterCustomBuffer + (w * h * this->_displayInfo.pixelBytes);
this->_displayInfo.renderedBuffer[NDSDisplayID_Main] = (this->_displayInfo.didPerformCustomRender[NDSDisplayID_Main]) ? this->_displayInfo.customBuffer[NDSDisplayID_Main] : this->_displayInfo.nativeBuffer[NDSDisplayID_Main];
this->_displayInfo.renderedBuffer[NDSDisplayID_Touch] = (this->_displayInfo.didPerformCustomRender[NDSDisplayID_Touch]) ? this->_displayInfo.customBuffer[NDSDisplayID_Touch] : this->_displayInfo.nativeBuffer[NDSDisplayID_Touch];
this->_engineMain->SetCustomFramebufferSize(w, h);
this->_engineSub->SetCustomFramebufferSize(w, h);
BaseRenderer->SetFramebufferSize(w, h); // Since BaseRenderer is persistent, we need to update this manually.
if (CurrentRenderer != BaseRenderer)
{
CurrentRenderer->RequestColorFormat(outputFormat);
CurrentRenderer->SetFramebufferSize(w, h);
}
free_aligned(oldCustomFramebuffer);
free_aligned(oldMasterFramebuffer);
free_aligned(oldCustomVRAM);
}
@ -7363,11 +7367,18 @@ void GPUSubsystem::SetWillAutoResolveToCustomBuffer(const bool willAutoResolve)
}
template <NDSColorFormat OUTPUTFORMAT>
void GPUSubsystem::RenderLine(const size_t l, bool isFrameSkipRequested)
void GPUSubsystem::RenderLine(const size_t l)
{
if (!this->_frameNeedsFinish)
{
this->_event->DidFrameBegin(isFrameSkipRequested);
u8 targetBufferIndex = this->_displayInfo.bufferIndex;
if ( (l == 0) && !this->_willFrameSkip )
{
targetBufferIndex = (targetBufferIndex + 1) & 0x01;
}
this->_event->DidFrameBegin(this->_willFrameSkip, targetBufferIndex, l);
this->_frameNeedsFinish = true;
}
@ -7380,13 +7391,13 @@ void GPUSubsystem::RenderLine(const size_t l, bool isFrameSkipRequested)
if (l == 0)
{
if (!isFrameSkipRequested)
if (!this->_willFrameSkip)
{
this->UpdateRenderProperties();
}
}
if ( (isFramebufferRenderNeeded[GPUEngineID_Main] || isDisplayCaptureNeeded) && !isFrameSkipRequested )
if ( (isFramebufferRenderNeeded[GPUEngineID_Main] || isDisplayCaptureNeeded) && !this->_willFrameSkip )
{
// GPUEngineA:WillRender3DLayer() and GPUEngineA:WillCapture3DLayerDirect() both rely on register
// states that might change on a per-line basis. Therefore, we need to check these states on a
@ -7419,7 +7430,7 @@ void GPUSubsystem::RenderLine(const size_t l, bool isFrameSkipRequested)
this->_engineMain->UpdatePropertiesWithoutRender(l);
}
if (isFramebufferRenderNeeded[GPUEngineID_Sub] && !isFrameSkipRequested)
if (isFramebufferRenderNeeded[GPUEngineID_Sub] && !this->_willFrameSkip)
{
this->_engineSub->RenderLine<OUTPUTFORMAT>(l);
}
@ -7435,7 +7446,7 @@ void GPUSubsystem::RenderLine(const size_t l, bool isFrameSkipRequested)
this->_UpdateFPSRender3D();
if (!isFrameSkipRequested)
if (!this->_willFrameSkip)
{
if (this->_displayInfo.isCustomSizeRequested)
{
@ -7498,7 +7509,7 @@ void GPUSubsystem::RenderLine(const size_t l, bool isFrameSkipRequested)
if (this->_frameNeedsFinish)
{
this->_frameNeedsFinish = false;
this->_event->DidFrameEnd(isFrameSkipRequested);
this->_event->DidFrameEnd(this->_willFrameSkip, this->_displayInfo);
}
}
}
@ -7529,13 +7540,11 @@ void GPUSubsystem::ClearWithColor(const u16 colorBGRA5551)
switch (this->_displayInfo.pixelBytes)
{
case 2:
memset_u16(this->_displayInfo.masterNativeBuffer, color16, GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2);
memset_u16(this->_displayInfo.masterCustomBuffer, color16, this->_displayInfo.customWidth * this->_displayInfo.customHeight * 2);
memset_u16(this->_masterFramebuffer, color16, (this->_displayInfo.framebufferSize * 2) / this->_displayInfo.pixelBytes);
break;
case 4:
memset_u32(this->_displayInfo.masterNativeBuffer, color32.color, GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2);
memset_u32(this->_displayInfo.masterCustomBuffer, color32.color, this->_displayInfo.customWidth * this->_displayInfo.customHeight * 2);
memset_u32(this->_masterFramebuffer, color32.color, (this->_displayInfo.framebufferSize * 2) / this->_displayInfo.pixelBytes);
break;
default:
@ -7543,6 +7552,93 @@ void GPUSubsystem::ClearWithColor(const u16 colorBGRA5551)
}
}
GPUClientFetchObject::GPUClientFetchObject()
{
memset(&_fetchDisplayInfo[0], 0, sizeof(NDSDisplayInfo));
memset(&_fetchDisplayInfo[1], 0, sizeof(NDSDisplayInfo));
_clientData = NULL;
_lastFetchIndex = 0;
}
void GPUClientFetchObject::Init()
{
// Do nothing. This is implementation dependent.
}
void GPUClientFetchObject::SetFetchBuffers(const NDSDisplayInfo &currentDisplayInfo)
{
// Do nothing. This is implementation dependent.
}
void GPUClientFetchObject::FetchFromBufferIndex(const u8 index)
{
if (this->_fetchDisplayInfo[index].isDisplayEnabled[NDSDisplayID_Main])
{
if (!this->_fetchDisplayInfo[index].didPerformCustomRender[NDSDisplayID_Main])
{
this->_FetchNativeDisplayByID(NDSDisplayID_Main, index);
}
else
{
this->_FetchCustomDisplayByID(NDSDisplayID_Main, index);
}
}
if (this->_fetchDisplayInfo[index].isDisplayEnabled[NDSDisplayID_Touch])
{
if (!this->_fetchDisplayInfo[index].didPerformCustomRender[NDSDisplayID_Touch])
{
this->_FetchNativeDisplayByID(NDSDisplayID_Touch, index);
}
else
{
this->_FetchCustomDisplayByID(NDSDisplayID_Touch, index);
}
}
this->SetLastFetchIndex(index);
}
void GPUClientFetchObject::_FetchNativeDisplayByID(const NDSDisplayID displayID, const u8 bufferIndex)
{
// Do nothing. This is implementation dependent.
}
void GPUClientFetchObject::_FetchCustomDisplayByID(const NDSDisplayID displayID, const u8 bufferIndex)
{
// Do nothing. This is implementation dependent.
}
const NDSDisplayInfo& GPUClientFetchObject::GetFetchDisplayInfoForBufferIndex(const u8 bufferIndex) const
{
return this->_fetchDisplayInfo[bufferIndex];
}
void GPUClientFetchObject::SetFetchDisplayInfo(const NDSDisplayInfo &displayInfo)
{
this->_fetchDisplayInfo[displayInfo.bufferIndex] = displayInfo;
}
u8 GPUClientFetchObject::GetLastFetchIndex() const
{
return this->_lastFetchIndex;
}
void GPUClientFetchObject::SetLastFetchIndex(const u8 fetchIndex)
{
this->_lastFetchIndex = fetchIndex;
}
void* GPUClientFetchObject::GetClientData() const
{
return this->_clientData;
}
void GPUClientFetchObject::SetClientData(void *clientData)
{
this->_clientData = clientData;
}
NDSDisplay::NDSDisplay()
{
_ID = NDSDisplayID_Main;
@ -7600,6 +7696,6 @@ template void GPUEngineBase::ParseReg_BGnY<GPULayerID_BG2>();
template void GPUEngineBase::ParseReg_BGnX<GPULayerID_BG3>();
template void GPUEngineBase::ParseReg_BGnY<GPULayerID_BG3>();
template void GPUSubsystem::RenderLine<NDSColorFormat_BGR555_Rev>(const size_t l, bool skip);
template void GPUSubsystem::RenderLine<NDSColorFormat_BGR666_Rev>(const size_t l, bool skip);
template void GPUSubsystem::RenderLine<NDSColorFormat_BGR888_Rev>(const size_t l, bool skip);
template void GPUSubsystem::RenderLine<NDSColorFormat_BGR555_Rev>(const size_t l);
template void GPUSubsystem::RenderLine<NDSColorFormat_BGR666_Rev>(const size_t l);
template void GPUSubsystem::RenderLine<NDSColorFormat_BGR888_Rev>(const size_t l);

View File

@ -2,7 +2,7 @@
Copyright (C) 2006 yopyop
Copyright (C) 2006-2007 Theo Berkau
Copyright (C) 2007 shash
Copyright (C) 2009-2016 DeSmuME team
Copyright (C) 2009-2017 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -1067,12 +1067,11 @@ typedef struct
// false - The user requested the native size.
size_t customWidth; // The requested custom width, measured in pixels.
size_t customHeight; // The requested custom height, measured in pixels.
size_t framebufferSize; // The size of a single framebuffer, which includes the native and custom buffers of both displays,
// measured in bytes.
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.
// 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().
@ -1089,9 +1088,21 @@ typedef struct
// Frame 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.
void *nativeBuffer[2]; // Pointer to the display's native size framebuffer.
void *customBuffer[2]; // Pointer to the display's custom size framebuffer.
size_t renderedWidth[2]; // The display rendered at this width, measured in pixels.
size_t renderedHeight[2]; // The display rendered at this height, measured in pixels.
void *renderedBuffer[2]; // The display rendered to this buffer.
bool didPerformCustomRender[2]; // Reports that the display actually rendered at a custom size for this frame.
// true - The display performed a custom-sized render.
// false - The display performed a native-sized render.
@ -1101,10 +1112,6 @@ typedef struct
// a master brightness intensity of 0 for all lines.
GPUMasterBrightMode 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.
size_t renderedWidth[2]; // The display rendered at this width, measured in pixels.
size_t renderedHeight[2]; // The display rendered at this height, measured in pixels.
void *renderedBuffer[2]; // The display rendered to this buffer.
} NDSDisplayInfo;
#define VRAM_NO_3D_USAGE 0xFF
@ -1622,8 +1629,8 @@ public:
class GPUEventHandler
{
public:
virtual void DidFrameBegin(bool isFrameSkipRequested) = 0;
virtual void DidFrameEnd(bool isFrameSkipped) = 0;
virtual void DidFrameBegin(bool isFrameSkipRequested, const u8 targetBufferIndex, const size_t line) = 0;
virtual void DidFrameEnd(bool isFrameSkipped, const NDSDisplayInfo &latestDisplayInfo) = 0;
virtual void DidRender3DBegin() = 0;
virtual void DidRender3DEnd() = 0;
};
@ -1634,8 +1641,8 @@ public:
class GPUEventHandlerDefault : public GPUEventHandler
{
public:
virtual void DidFrameBegin(bool isFrameSkipRequested) {};
virtual void DidFrameEnd(bool isFrameSkipped) {};
virtual void DidFrameBegin(bool isFrameSkipRequested, const u8 targetBufferIndex, const size_t line) {};
virtual void DidFrameEnd(bool isFrameSkipped, const NDSDisplayInfo &latestDisplayInfo) {};
virtual void DidRender3DBegin() {};
virtual void DidRender3DEnd() {};
};
@ -1643,9 +1650,6 @@ public:
class GPUSubsystem
{
private:
GPUSubsystem();
~GPUSubsystem();
GPUEventHandlerDefault *_defaultEventHandler;
GPUEventHandler *_event;
@ -1657,23 +1661,23 @@ private:
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 _willAutoResolveToCustomBuffer;
u16 *_customVRAM;
u16 *_customVRAMBlank;
CACHE_ALIGN FragmentColor _nativeFramebuffer[GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2];
void *_customFramebuffer;
void *_masterFramebuffer;
NDSDisplayInfo _displayInfo;
void _UpdateFPSRender3D();
void _AllocateFramebuffers(NDSColorFormat outputFormat, size_t w, size_t h, void *clientNativeBuffer, void *clientCustomBuffer);
void _AllocateFramebuffers(NDSColorFormat outputFormat, size_t w, size_t h);
public:
static GPUSubsystem* Allocate();
void FinalizeAndDeallocate();
GPUSubsystem();
~GPUSubsystem();
void SetEventHandler(GPUEventHandler *eventHandler);
GPUEventHandler* GetEventHandler();
@ -1698,11 +1702,11 @@ public:
size_t GetCustomFramebufferWidth() const;
size_t GetCustomFramebufferHeight() const;
void SetCustomFramebufferSize(size_t w, size_t h, void *clientNativeBuffer, void *clientCustomBuffer);
void SetCustomFramebufferSize(size_t w, size_t h);
void SetColorFormat(const NDSColorFormat outputFormat, void *clientNativeBuffer, void *clientCustomBuffer);
void SetColorFormat(const NDSColorFormat outputFormat);
bool GetWillFrameSkip() const;
void SetWillFrameSkip(const bool willFrameSkip);
void UpdateRenderProperties();
// By default, the output framebuffer will have the master brightness applied before
@ -1741,10 +1745,38 @@ public:
bool GetWillAutoResolveToCustomBuffer() const;
void SetWillAutoResolveToCustomBuffer(const bool willAutoResolve);
template<NDSColorFormat OUTPUTFORMAT> void RenderLine(const size_t l, bool skip = false);
template<NDSColorFormat OUTPUTFORMAT> void RenderLine(const size_t l);
void ClearWithColor(const u16 colorBGRA5551);
};
class GPUClientFetchObject
{
protected:
NDSDisplayInfo _fetchDisplayInfo[2];
volatile u8 _lastFetchIndex;
void *_clientData;
virtual void _FetchNativeDisplayByID(const NDSDisplayID displayID, const u8 bufferIndex);
virtual void _FetchCustomDisplayByID(const NDSDisplayID displayID, const u8 bufferIndex);
public:
GPUClientFetchObject();
virtual ~GPUClientFetchObject() {};
virtual void Init();
virtual void SetFetchBuffers(const NDSDisplayInfo &currentDisplayInfo);
virtual void FetchFromBufferIndex(const u8 index);
u8 GetLastFetchIndex() const;
void SetLastFetchIndex(const u8 fetchIndex);
const NDSDisplayInfo& GetFetchDisplayInfoForBufferIndex(const u8 bufferIndex) const;
void SetFetchDisplayInfo(const NDSDisplayInfo &displayInfo);
void* GetClientData() const;
void SetClientData(void *clientData);
};
extern GPUSubsystem *GPU;
extern MMU_struct MMU;

View File

@ -173,12 +173,8 @@ int NDS_Init()
NDS_ARM7.SetBaseMemoryInterfaceData(NULL);
NDS_ARM7.ResetMemoryInterfaceToBase();
if (GPU != NULL)
{
GPU->FinalizeAndDeallocate();
}
GPU = GPUSubsystem::Allocate();
delete GPU;
GPU = new GPUSubsystem;
if (SPU_Init(SNDCORE_DUMMY, 740) != 0)
return -1;
@ -196,7 +192,7 @@ void NDS_DeInit(void)
gameInfo.closeROM();
SPU_DeInit();
GPU->FinalizeAndDeallocate();
delete GPU;
GPU = NULL;
MMU_DeInit();
@ -1302,18 +1298,23 @@ static void execHardware_hblank()
//scroll regs for the next scanline
if(nds.VCount<192)
{
if (nds.VCount == 0)
{
GPU->SetWillFrameSkip(frameSkipper.ShouldSkip2D());
}
switch (GPU->GetDisplayInfo().colorFormat)
{
case NDSColorFormat_BGR555_Rev:
GPU->RenderLine<NDSColorFormat_BGR555_Rev>(nds.VCount, frameSkipper.ShouldSkip2D());
GPU->RenderLine<NDSColorFormat_BGR555_Rev>(nds.VCount);
break;
case NDSColorFormat_BGR666_Rev:
GPU->RenderLine<NDSColorFormat_BGR666_Rev>(nds.VCount, frameSkipper.ShouldSkip2D());
GPU->RenderLine<NDSColorFormat_BGR666_Rev>(nds.VCount);
break;
case NDSColorFormat_BGR888_Rev:
GPU->RenderLine<NDSColorFormat_BGR888_Rev>(nds.VCount, frameSkipper.ShouldSkip2D());
GPU->RenderLine<NDSColorFormat_BGR888_Rev>(nds.VCount);
break;
}

View File

@ -68,8 +68,8 @@ public:
void SetOutputList(NSMutableArray *outputList, pthread_mutex_t *theMutex);
bool GetRender3DNeedsFinish();
virtual void DidFrameBegin(bool isFrameSkipRequested);
virtual void DidFrameEnd(bool isFrameSkipped);
virtual void DidFrameBegin(bool isFrameSkipRequested, const u8 targetBufferIndex, const size_t line);
virtual void DidFrameEnd(bool isFrameSkipped, const NDSDisplayInfo &latestDisplayInfo);
virtual void DidRender3DBegin();
virtual void DidRender3DEnd();
};
@ -833,12 +833,12 @@ GPUEventHandlerOSX::~GPUEventHandlerOSX()
pthread_mutex_destroy(&this->_mutex3DRender);
}
void GPUEventHandlerOSX::DidFrameBegin(bool isFrameSkipRequested)
void GPUEventHandlerOSX::DidFrameBegin(bool isFrameSkipRequested, const u8 targetBufferIndex, const size_t line)
{
this->FramebufferLockWrite();
}
void GPUEventHandlerOSX::DidFrameEnd(bool isFrameSkipped)
void GPUEventHandlerOSX::DidFrameEnd(bool isFrameSkipped, const NDSDisplayInfo &latestDisplayInfo)
{
this->FramebufferUnlock();