Permalink
Browse files

GPU: No more need for clients to specify whether to apply the master …

…brightness on a per-scanline basis or on a per-framebuffer basis; GPUSubsystem can now automatically switch between applying per-scanline or applying per-framebuffer.
  • Loading branch information...
rogerman committed Feb 23, 2017
1 parent 7031bd9 commit 8dd7c9b924938c45af538775a6aff3ddd4a145a9
Showing with 34 additions and 53 deletions.
  1. +31 −36 desmume/src/GPU.cpp
  2. +3 −17 desmume/src/GPU.h
View
@@ -353,8 +353,6 @@ GPUEngineBase::GPUEngineBase()
_enableColorEffectCustom[GPULayerID_BG2] = NULL;
_enableColorEffectCustom[GPULayerID_BG3] = NULL;
_enableColorEffectCustom[GPULayerID_OBJ] = NULL;
_willApplyMasterBrightnessPerScanline = true;
}
GPUEngineBase::~GPUEngineBase()
@@ -4014,54 +4012,52 @@ void GPUEngineBase::_RenderLine_LayerOBJ(GPUEngineCompositorInfo &compInfo, item
}
}
bool GPUEngineBase::WillApplyMasterBrightnessPerScanline() const
{
return this->_willApplyMasterBrightnessPerScanline;
}
void GPUEngineBase::SetWillApplyMasterBrightnessPerScanline(bool willApply)
{
this->_willApplyMasterBrightnessPerScanline = willApply;
}
void GPUEngineBase::UpdateMasterBrightnessDisplayInfo(NDSDisplayInfo &mutableInfo)
{
if (this->_willApplyMasterBrightnessPerScanline)
const GPUEngineCompositorInfo &compInfoZero = this->_currentCompositorInfo[0];
bool needsApply = false;
bool processPerScanline = false;
for (size_t line = 0; line < GPU_FRAMEBUFFER_NATIVE_HEIGHT; line++)
{
bool needsApply = false;
const GPUEngineCompositorInfo &compInfo = this->_currentCompositorInfo[line];
for (size_t line = 0; line < GPU_FRAMEBUFFER_NATIVE_HEIGHT; line++)
if ( !needsApply &&
(compInfo.renderState.masterBrightnessIntensity != 0) &&
((compInfo.renderState.masterBrightnessMode == GPUMasterBrightMode_Up) || (compInfo.renderState.masterBrightnessMode == GPUMasterBrightMode_Down)) )
{
const GPUEngineCompositorInfo &compInfo = this->_currentCompositorInfo[line];
if ( (compInfo.renderState.masterBrightnessIntensity != 0) && ((compInfo.renderState.masterBrightnessMode == GPUMasterBrightMode_Up) || (compInfo.renderState.masterBrightnessMode == GPUMasterBrightMode_Down)) )
{
needsApply = true;
}
mutableInfo.masterBrightnessMode[this->_targetDisplayID][line] = compInfo.renderState.masterBrightnessMode;
mutableInfo.masterBrightnessIntensity[this->_targetDisplayID][line] = compInfo.renderState.masterBrightnessIntensity;
needsApply = true;
}
mutableInfo.needApplyMasterBrightness[this->_targetDisplayID] = needsApply;
}
else
{
const GPUEngineCompositorInfo &compInfo = this->_currentCompositorInfo[0];
mutableInfo.needApplyMasterBrightness[this->_targetDisplayID] = (compInfo.renderState.masterBrightnessIntensity != 0) && ((compInfo.renderState.masterBrightnessMode == GPUMasterBrightMode_Up) || (compInfo.renderState.masterBrightnessMode == GPUMasterBrightMode_Down));
mutableInfo.masterBrightnessMode[this->_targetDisplayID][line] = compInfo.renderState.masterBrightnessMode;
mutableInfo.masterBrightnessIntensity[this->_targetDisplayID][line] = compInfo.renderState.masterBrightnessIntensity;
for (size_t line = 0; line < GPU_FRAMEBUFFER_NATIVE_HEIGHT; line++)
if ( !processPerScanline &&
((compInfo.renderState.masterBrightnessMode != compInfoZero.renderState.masterBrightnessMode) ||
(compInfo.renderState.masterBrightnessIntensity != compInfoZero.renderState.masterBrightnessIntensity)) )
{
mutableInfo.masterBrightnessMode[this->_targetDisplayID][line] = compInfo.renderState.masterBrightnessMode;
mutableInfo.masterBrightnessIntensity[this->_targetDisplayID][line] = compInfo.renderState.masterBrightnessIntensity;
processPerScanline = true;
}
}
mutableInfo.masterBrightnessDiffersPerLine[this->_targetDisplayID] = processPerScanline;
mutableInfo.needApplyMasterBrightness[this->_targetDisplayID] = needsApply;
}
template <NDSColorFormat OUTPUTFORMAT>
void GPUEngineBase::ApplyMasterBrightness(const NDSDisplayInfo &displayInfo)
{
if (this->_willApplyMasterBrightnessPerScanline)
// Most games maintain the exact same master brightness values for all 192 lines, so we
// can easily apply the master brightness to the entire framebuffer at once, which is
// faster than applying it per scanline.
//
// However, some games need to have the master brightness values applied on a per-scanline
// basis since they can differ for each scanline. For example, Mega Man Zero Collection
// purposely changes the master brightness intensity to 31 on line 0, 0 on line 16, and
// then back to 31 on line 176. Since the MMZC are originally GBA games, the master
// brightness intensity changes are done to disable the unused scanlines on the NDS.
if (displayInfo.masterBrightnessDiffersPerLine[this->_targetDisplayID])
{
for (size_t line = 0; line < GPU_FRAMEBUFFER_NATIVE_HEIGHT; line++)
{
@@ -7428,8 +7424,7 @@ void GPUSubsystem::RenderLine(const size_t l)
this->_engineSub->UpdateRenderStates(l);
const bool isDisplayCaptureNeeded = this->_engineMain->WillDisplayCapture(l);
const bool isFramebufferRenderNeeded[2] = { CommonSettings.showGpu.main && ( !this->_engineMain->IsMasterBrightFullIntensityAtLineZero() || this->_engineMain->WillApplyMasterBrightnessPerScanline() ),
CommonSettings.showGpu.sub && ( !this->_engineSub->IsMasterBrightFullIntensityAtLineZero() || this->_engineSub->WillApplyMasterBrightnessPerScanline() ) };
const bool isFramebufferRenderNeeded[2] = { CommonSettings.showGpu.main, CommonSettings.showGpu.sub };
if (l == 0)
{
View
@@ -1098,6 +1098,9 @@ typedef struct
// true - The display performed a custom-sized render.
// false - The display performed a native-sized render.
bool masterBrightnessDiffersPerLine[2]; // Reports if the master brightness values may differ per scanline. If true, then it will
// need to be applied on a per-scanline basis. Otherwise, it can be applied to the entire
// framebuffer. For most NDS games, this field will be false.
u8 masterBrightnessMode[2][GPU_FRAMEBUFFER_NATIVE_HEIGHT]; // The master brightness mode of each display line.
u8 masterBrightnessIntensity[2][GPU_FRAMEBUFFER_NATIVE_HEIGHT]; // The master brightness intensity of each display line.
@@ -1328,7 +1331,6 @@ class GPUEngineBase
CACHE_ALIGN u8 _h_win[2][GPU_FRAMEBUFFER_NATIVE_WIDTH];
NDSDisplayID _targetDisplayID;
bool _willApplyMasterBrightnessPerScanline;
CACHE_ALIGN FragmentColor _internalRenderLineTargetNative[GPU_FRAMEBUFFER_NATIVE_WIDTH];
CACHE_ALIGN u8 _renderLineLayerIDNative[GPU_FRAMEBUFFER_NATIVE_WIDTH];
@@ -1481,22 +1483,6 @@ class GPUEngineBase
bool GetLayerEnableState(const size_t layerIndex);
void SetLayerEnableState(const size_t layerIndex, bool theState);
// By default, the master brightness will be applied on a per-scanline basis. This is
// necessary for certain games, such as Mega Man Zero Collection, that purposely change
// the the master brightness in the middle of the frame. With this particular game, it
// will change the master brightness to 31 on line 0, 0 on line 16, and back to 31 on
// line 176. Originally being a GBA game, this is done to disable unused scanlines on
// the NDS.
//
// However, applying the master brightness per scanline is slower than applying it on
// the entire framebuffer. To apply the master brightness to the entire framebuffer
// instead, call SetWillApplyMasterBrightnessPerScanline() and pass a value of "false".
// This should be safe for the vast majority of games, since games usually won't change
// the master brightness mid-frame, and even those that do will look fine when using
// the master brightness value from line 0.
bool WillApplyMasterBrightnessPerScanline() const;
void SetWillApplyMasterBrightnessPerScanline(bool willApply);
void UpdateMasterBrightnessDisplayInfo(NDSDisplayInfo &mutableInfo);
template<NDSColorFormat OUTPUTFORMAT> void ApplyMasterBrightness(const NDSDisplayInfo &displayInfo);
template<NDSColorFormat OUTPUTFORMAT, bool ISFULLINTENSITYHINT> void ApplyMasterBrightness(void *dst, const size_t pixCount, const GPUMasterBrightMode mode, const u8 intensity);

0 comments on commit 8dd7c9b

Please sign in to comment.