diff --git a/desmume/src/GPU.cpp b/desmume/src/GPU.cpp index 82a5da1a2..cbf098329 100644 --- a/desmume/src/GPU.cpp +++ b/desmume/src/GPU.cpp @@ -6762,6 +6762,8 @@ GPUSubsystem::GPUSubsystem() _videoFrameCount = 0; _render3DFrameCount = 0; _frameNeedsFinish = false; + _willAutoApplyMasterBrightness = true; + _willAutoConvertRGB666ToRGB888 = true; _willAutoResolveToCustomBuffer = true; OSDCLASS *previousOSD = osd; @@ -7305,6 +7307,26 @@ u16* GPUSubsystem::GetCustomVRAMAddressUsingMappedAddress(const u32 mappedAddr) return (this->GetEngineMain()->GetCustomVRAMBlockPtr(blockID) + (_gpuCaptureLineIndex[blockLine] * this->_displayInfo.customWidth) + _gpuDstPitchIndex[linePixel]); } +bool GPUSubsystem::GetWillAutoApplyMasterBrightness() const +{ + return this->_willAutoApplyMasterBrightness; +} + +void GPUSubsystem::SetWillAutoApplyMasterBrightness(const bool willAutoApply) +{ + this->_willAutoApplyMasterBrightness = willAutoApply; +} + +bool GPUSubsystem::GetWillAutoConvertRGB666ToRGB888() const +{ + return this->_willAutoConvertRGB666ToRGB888; +} + +void GPUSubsystem::SetWillAutoConvertRGB666ToRGB888(const bool willAutoConvert) +{ + this->_willAutoConvertRGB666ToRGB888 = willAutoConvert; +} + bool GPUSubsystem::GetWillAutoResolveToCustomBuffer() const { return this->_willAutoResolveToCustomBuffer; @@ -7319,7 +7341,7 @@ template void GPUSubsystem::RenderLine(const u16 l, bool isFrameSkipRequested) { const bool isDisplayCaptureNeeded = this->_engineMain->WillDisplayCapture(l); - const bool isFramebufferRenderNeeded[2] = {(CommonSettings.showGpu.main && !this->_engineMain->GetIsMasterBrightFullIntensity()) || isDisplayCaptureNeeded, + const bool isFramebufferRenderNeeded[2] = { CommonSettings.showGpu.main && !this->_engineMain->GetIsMasterBrightFullIntensity(), CommonSettings.showGpu.sub && !this->_engineSub->GetIsMasterBrightFullIntensity() }; if (!this->_frameNeedsFinish) @@ -7337,7 +7359,7 @@ void GPUSubsystem::RenderLine(const u16 l, bool isFrameSkipRequested) } } - if (isFramebufferRenderNeeded[GPUEngineID_Main] && !isFrameSkipRequested) + if ( (isFramebufferRenderNeeded[GPUEngineID_Main] || isDisplayCaptureNeeded) && !isFrameSkipRequested ) { // 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 @@ -7410,39 +7432,42 @@ void GPUSubsystem::RenderLine(const u16 l, bool isFrameSkipRequested) this->_displayInfo.renderedWidth[NDSDisplayID_Touch] = this->_displayTouch->GetEngine()->renderedWidth; this->_displayInfo.renderedHeight[NDSDisplayID_Touch] = this->_displayTouch->GetEngine()->renderedHeight; - if (isFramebufferRenderNeeded[GPUEngineID_Main]) + if (this->_willAutoApplyMasterBrightness) { - this->_engineMain->ApplyMasterBrightness(); - } - else - { - if (!CommonSettings.showGpu.main) + if (CommonSettings.showGpu.main) + { + if (this->_engineMain->GetIsMasterBrightFullIntensity()) + { + this->_engineMain->ApplyMasterBrightness(); + } + else + { + this->_engineMain->ApplyMasterBrightness(); + } + } + else { memset(this->_engineMain->renderedBuffer, 0, this->_engineMain->renderedWidth * this->_engineMain->renderedHeight * this->_displayInfo.pixelBytes); } - else if (this->_engineMain->GetIsMasterBrightFullIntensity()) + + if (CommonSettings.showGpu.sub) { - this->_engineMain->ApplyMasterBrightness(); + if (this->_engineSub->GetIsMasterBrightFullIntensity()) + { + this->_engineSub->ApplyMasterBrightness(); + } + else + { + this->_engineSub->ApplyMasterBrightness(); + } } - } - - if (isFramebufferRenderNeeded[GPUEngineID_Sub]) - { - this->_engineSub->ApplyMasterBrightness(); - } - else - { - if (!CommonSettings.showGpu.sub) + else { memset(this->_engineSub->renderedBuffer, 0, this->_engineSub->renderedWidth * this->_engineSub->renderedHeight * this->_displayInfo.pixelBytes); } - else if (this->_engineSub->GetIsMasterBrightFullIntensity()) - { - this->_engineSub->ApplyMasterBrightness(); - } } - if (OUTPUTFORMAT == NDSColorFormat_BGR666_Rev) + if ( (OUTPUTFORMAT == NDSColorFormat_BGR666_Rev) && this->_willAutoConvertRGB666ToRGB888 ) { this->_engineMain->ResolveRGB666ToRGB888(); this->_engineSub->ResolveRGB666ToRGB888(); diff --git a/desmume/src/GPU.h b/desmume/src/GPU.h index 00883a3ce..7d194481b 100644 --- a/desmume/src/GPU.h +++ b/desmume/src/GPU.h @@ -1611,6 +1611,8 @@ 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 _willAutoApplyMasterBrightness; + bool _willAutoConvertRGB666ToRGB888; bool _willAutoResolveToCustomBuffer; u16 *_customVRAM; u16 *_customVRAMBlank; @@ -1656,6 +1658,26 @@ public: void UpdateRenderProperties(); + // By default, the output framebuffer will have the master brightness applied before + // the DidFrameEnd event. The master brightness is applied using the CPU. + // + // To turn off this behavior, call SetWillAutoApplyMasterBrightness() and pass a value + // of "false". This can be useful if the client wants to apply the master brightness + // itself, for example, if a client applies it on the GPU. + bool GetWillAutoApplyMasterBrightness() const; + void SetWillAutoApplyMasterBrightness(const bool willAutoApply); + + // By default, if the output framebuffer is in RGB666 format, then the framebuffers will + // automatically be converted to the much more common RGB888 format. This conversion is + // performed on the CPU. + // + // To turn off this behavior, call SetWillAutoConvertRGB666ToRGB888() and pass a value + // of "false". This can be useful if the client wants to do its own post-processing + // while the color format is still RGB666, or if the client wants to do its own custom + // conversion (such as converting the framebuffer later on the GPU). + bool GetWillAutoConvertRGB666ToRGB888() const; + void SetWillAutoConvertRGB666ToRGB888(const bool willAutoConvert); + // 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 // within a single common buffer. This is necessary for when someone wants to read