diff --git a/desmume/src/GPU.cpp b/desmume/src/GPU.cpp index 891a1295b..813651f2a 100644 --- a/desmume/src/GPU.cpp +++ b/desmume/src/GPU.cpp @@ -266,12 +266,8 @@ GPUEngineBase::~GPUEngineBase() this->_enableColorEffectCustom[GPULayerID_OBJ] = NULL; } -void GPUEngineBase::_Reset_Base() +void GPUEngineBase::Reset() { - const NDSDisplayInfo &dispInfo = GPU->GetDisplayInfo(); - - this->_needExpandSprColorCustom = false; - this->SetupBuffers(); memset(this->_sprColor, 0, sizeof(this->_sprColor)); @@ -279,7 +275,7 @@ void GPUEngineBase::_Reset_Base() memset(this->_didPassWindowTestNative, 0xFF, 5 * GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(u8)); memset(this->_enableColorEffectNative, 0xFF, 5 * GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(u8)); - memset(this->_didPassWindowTestCustomMasterPtr, 0xFF, 10 * dispInfo.customWidth * sizeof(u8)); + memset(this->_didPassWindowTestCustomMasterPtr, 0xFF, 10 * this->_targetDisplay->GetWidth() * sizeof(u8)); memset(this->_h_win[0], 0, sizeof(this->_h_win[0])); memset(this->_h_win[1], 0, sizeof(this->_h_win[1])); @@ -290,9 +286,11 @@ void GPUEngineBase::_Reset_Base() if (this->_internalRenderLineTargetCustom != NULL) { - memset(this->_internalRenderLineTargetCustom, 0, dispInfo.customWidth * dispInfo.customHeight * dispInfo.pixelBytes); + memset(this->_internalRenderLineTargetCustom, 0, this->_targetDisplay->GetWidth() * this->_targetDisplay->GetHeight() * this->_targetDisplay->GetPixelBytes()); } + this->_needExpandSprColorCustom = false; + this->_isBGLayerShown[GPULayerID_BG0] = false; this->_isBGLayerShown[GPULayerID_BG1] = false; this->_isBGLayerShown[GPULayerID_BG2] = false; @@ -352,6 +350,17 @@ void GPUEngineBase::_Reset_Base() this->_vramBlockOBJAddress = 0; + this->savedBG2X.value = 0; + this->savedBG2Y.value = 0; + this->savedBG3X.value = 0; + this->savedBG3Y.value = 0; + + this->_asyncClearTransitionedLineFromBackdropCount = 0; + this->_asyncClearLineCustom = 0; + this->_asyncClearInterrupt = 0; + this->_asyncClearIsRunning = false; + this->_asyncClearUseInternalCustomBuffer = false; + for (size_t l = 0; l < GPU_FRAMEBUFFER_NATIVE_HEIGHT; l++) { this->_isLineRenderNative[l] = true; @@ -365,7 +374,7 @@ void GPUEngineBase::_Reset_Base() renderState.selectedBGLayer = &this->_BGLayer[GPULayerID_BG0]; renderState.backdropColor16 = LE_TO_LOCAL_16(this->_paletteBG[0]) & 0x7FFF; renderState.workingBackdropColor16 = renderState.backdropColor16; - renderState.workingBackdropColor32.color = LOCAL_TO_LE_32( (dispInfo.colorFormat == NDSColorFormat_BGR666_Rev) ? COLOR555TO666(LOCAL_TO_LE_16(renderState.workingBackdropColor16)) : COLOR555TO888(LOCAL_TO_LE_16(renderState.workingBackdropColor16)) ); + renderState.workingBackdropColor32.color = LOCAL_TO_LE_32( (this->_targetDisplay->GetColorFormat() == NDSColorFormat_BGR666_Rev) ? COLOR555TO666(LOCAL_TO_LE_16(renderState.workingBackdropColor16)) : COLOR555TO888(LOCAL_TO_LE_16(renderState.workingBackdropColor16)) ); renderState.colorEffect = (ColorEffect)this->_IORegisterMap->BLDCNT.ColorEffect; renderState.blendEVA = 0; renderState.blendEVB = 0; @@ -408,28 +417,12 @@ void GPUEngineBase::_Reset_Base() renderState.spriteBoundary = 0; renderState.spriteBMPBoundary = 0; - this->savedBG2X.value = 0; - this->savedBG2Y.value = 0; - this->savedBG3X.value = 0; - this->savedBG3Y.value = 0; - - this->_asyncClearTransitionedLineFromBackdropCount = 0; - this->_asyncClearLineCustom = 0; - this->_asyncClearInterrupt = 0; - this->_asyncClearIsRunning = false; - this->_asyncClearUseInternalCustomBuffer = false; - for (size_t line = 0; line < GPU_VRAM_BLOCK_LINES + 1; line++) { this->_currentCompositorInfo[line].renderState = renderState; } } -void GPUEngineBase::Reset() -{ - this->_Reset_Base(); -} - void GPUEngineBase::_ResortBGLayers() { const IOREG_DISPCNT &DISPCNT = this->_IORegisterMap->DISPCNT; @@ -679,12 +672,9 @@ void* GPUEngine_RunClearAsynchronous(void *arg) template void GPUEngineBase::RenderLineClearAsync() { - const NDSDisplayInfo &dispInfo = GPU->GetDisplayInfo(); - const bool isCustomClearNeeded = dispInfo.isCustomSizeRequested; - s32 asyncClearLineCustom = atomic_and_barrier32(&this->_asyncClearLineCustom, 0x000000FF); - if (isCustomClearNeeded) + if (this->_targetDisplay->IsCustomSizeRequested()) { // Note that the following variables are not explicitly synchronized, and therefore are expected // to remain constant while this thread is running: @@ -792,8 +782,6 @@ void GPUEngineBase::_RenderLine_Clear(GPUEngineCompositorInfo &compInfo) void GPUEngineBase::SetupBuffers() { - const NDSDisplayInfo &dispInfo = GPU->GetDisplayInfo(); - memset(this->_renderLineLayerIDNative, GPULayerID_Backdrop, GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT); memset(this->_sprAlpha, 0, GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT); @@ -801,11 +789,11 @@ void GPUEngineBase::SetupBuffers() memset(this->_sprPrio, 0x7F, GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT); memset(this->_sprWin, 0, GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT); - if (dispInfo.isCustomSizeRequested) + if (this->_targetDisplay->IsCustomSizeRequested()) { if (this->_renderLineLayerIDCustom != NULL) { - memset(this->_renderLineLayerIDCustom, GPULayerID_Backdrop, dispInfo.customWidth * (dispInfo.customHeight + (_gpuLargestDstLineCount * 4)) * sizeof(u8)); + memset(this->_renderLineLayerIDCustom, GPULayerID_Backdrop, this->_targetDisplay->GetWidth() * (this->_targetDisplay->GetHeight() + (_gpuLargestDstLineCount * 4)) * sizeof(u8)); } } } @@ -878,16 +866,14 @@ void GPUEngineBase::UpdateRenderStates(const size_t l) // Handle the asynchronous custom line clearing thread. if (compInfo.line.indexNative == 0) { - const NDSDisplayInfo &dispInfo = GPU->GetDisplayInfo(); - // If, in the last frame, we transitioned all 192 lines directly from the backdrop layer, // then we'll assume that this current frame will also do the same. Therefore, we will // attempt to asynchronously clear all of the custom lines with the backdrop color as an // optimization. - const bool wasPreviousHDFrameFullyTransitionedFromBackdrop = (this->_asyncClearTransitionedLineFromBackdropCount >= 192); + const bool wasPreviousHDFrameFullyTransitionedFromBackdrop = (this->_asyncClearTransitionedLineFromBackdropCount >= GPU_FRAMEBUFFER_NATIVE_HEIGHT); this->_asyncClearTransitionedLineFromBackdropCount = 0; - if (dispInfo.isCustomSizeRequested && wasPreviousHDFrameFullyTransitionedFromBackdrop) + if (this->_targetDisplay->IsCustomSizeRequested() && wasPreviousHDFrameFullyTransitionedFromBackdrop) { this->RenderLineClearAsyncStart((compInfo.renderState.displayOutputMode != GPUDisplayMode_Normal), compInfo.line.indexNative, @@ -2296,13 +2282,13 @@ void GPUEngineBase::_SpriteRenderPerform(GPUEngineCompositorInfo &compInfo, u16 template void GPUEngineBase::_RenderLine_Layers(GPUEngineCompositorInfo &compInfo) { - const NDSDisplayInfo &dispInfo = GPU->GetDisplayInfo(); + const size_t customPixelBytes = this->_targetDisplay->GetPixelBytes(); itemsForPriority_t *item; // Optimization: For normal display mode, render straight to the output buffer when that is what we are going to end // up displaying anyway. Otherwise, we need to use the working buffer. compInfo.target.lineColorHeadNative = (compInfo.renderState.displayOutputMode == GPUDisplayMode_Normal) ? this->_targetDisplay->GetNativeBuffer16() + compInfo.line.blockOffsetNative : this->_internalRenderLineTargetNative; - compInfo.target.lineColorHeadCustom = (compInfo.renderState.displayOutputMode == GPUDisplayMode_Normal) ? (u8 *)this->_targetDisplay->GetCustomBuffer() + (compInfo.line.blockOffsetCustom * dispInfo.pixelBytes) : (u8 *)this->_internalRenderLineTargetCustom + (compInfo.line.blockOffsetCustom * dispInfo.pixelBytes); + compInfo.target.lineColorHeadCustom = (compInfo.renderState.displayOutputMode == GPUDisplayMode_Normal) ? (u8 *)this->_targetDisplay->GetCustomBuffer() + (compInfo.line.blockOffsetCustom * customPixelBytes) : (u8 *)this->_internalRenderLineTargetCustom + (compInfo.line.blockOffsetCustom * customPixelBytes); compInfo.target.lineColorHead = compInfo.target.lineColorHeadNative; compInfo.target.lineLayerIDHeadNative = this->_renderLineLayerIDNative[compInfo.line.indexNative]; @@ -2462,7 +2448,7 @@ void GPUEngineBase::_RenderLine_SetupSprites(GPUEngineCompositorInfo &compInfo) item->nbPixelsX++; } - if ( (compInfo.line.widthCustom > GPU_FRAMEBUFFER_NATIVE_WIDTH) || (GPU->GetDisplayInfo().colorFormat != NDSColorFormat_BGR555_Rev) ) + if ( (compInfo.line.widthCustom > GPU_FRAMEBUFFER_NATIVE_WIDTH) || (this->_targetDisplay->GetColorFormat() != NDSColorFormat_BGR555_Rev) ) { bool isLineComplete = false; @@ -2704,7 +2690,7 @@ void GPUEngineBase::ApplyMasterBrightness(const NDSDisplayInfo &displayInfo) for (size_t line = 0; line < GPU_FRAMEBUFFER_NATIVE_HEIGHT; line++) { const GPUEngineLineInfo &lineInfo = GPU->GetLineInfoAtIndex(line); - void *dstColorLine = (!this->_targetDisplay->DidPerformCustomRender()) ? ((u8 *)this->_targetDisplay->GetNativeBuffer16() + (lineInfo.blockOffsetNative * sizeof(u16))) : ((u8 *)this->_targetDisplay->GetCustomBuffer() + (lineInfo.blockOffsetCustom * displayInfo.pixelBytes)); + void *dstColorLine = (!this->_targetDisplay->DidPerformCustomRender()) ? ((u8 *)this->_targetDisplay->GetNativeBuffer16() + (lineInfo.blockOffsetNative * sizeof(u16))) : ((u8 *)this->_targetDisplay->GetCustomBuffer() + (lineInfo.blockOffsetCustom * this->_targetDisplay->GetPixelBytes())); const size_t pixCount = (!this->_targetDisplay->DidPerformCustomRender()) ? GPU_FRAMEBUFFER_NATIVE_WIDTH : lineInfo.pixelCount; this->ApplyMasterBrightness(dstColorLine, @@ -3279,7 +3265,7 @@ void GPUEngineBase::AllocateWorkingBuffers(NDSColorFormat requestedColorFormat, u8 *oldSprTypeCustom = this->_sprTypeCustom; u8 *oldDidPassWindowTestCustomMasterPtr = this->_didPassWindowTestCustomMasterPtr; - this->_internalRenderLineTargetCustom = malloc_alignedPage(w * h * GPU->GetDisplayInfo().pixelBytes); + this->_internalRenderLineTargetCustom = malloc_alignedPage(w * h * this->_targetDisplay->GetPixelBytes()); this->_renderLineLayerIDCustom = (u8 *)malloc_alignedPage(w * (h + (_gpuLargestDstLineCount * 4)) * sizeof(u8)); // yes indeed, this is oversized. map debug tools try to write to it this->_deferredIndexCustom = (u8 *)malloc_alignedPage(w * sizeof(u8)); this->_deferredColorCustom = (u16 *)malloc_alignedPage(w * sizeof(u16)); @@ -3310,7 +3296,7 @@ void GPUEngineBase::AllocateWorkingBuffers(NDSColorFormat requestedColorFormat, for (size_t line = 0; line < GPU_VRAM_BLOCK_LINES + 1; line++) { this->_currentCompositorInfo[line].line = GPU->GetLineInfoAtIndex(line); - this->_currentCompositorInfo[line].target.lineColor = (GPU->GetDisplayInfo().colorFormat == NDSColorFormat_BGR555_Rev) ? (void **)&this->_currentCompositorInfo[line].target.lineColor16 : (void **)&this->_currentCompositorInfo[line].target.lineColor32; + this->_currentCompositorInfo[line].target.lineColor = (this->_targetDisplay->GetColorFormat() == NDSColorFormat_BGR555_Rev) ? (void **)&this->_currentCompositorInfo[line].target.lineColor16 : (void **)&this->_currentCompositorInfo[line].target.lineColor32; } free_aligned(oldWorkingLineColor); @@ -3457,8 +3443,19 @@ void GPUEngineA::FinalizeAndDeallocate() void GPUEngineA::Reset() { - const NDSDisplayInfo &dispInfo = GPU->GetDisplayInfo(); - this->_Reset_Base(); + this->SetTargetDisplay( GPU->GetDisplayMain() ); + this->GPUEngineBase::Reset(); + + const size_t customWidth = this->_targetDisplay->GetWidth(); + const size_t customHeight = this->_targetDisplay->GetHeight(); + + memset(this->_3DFramebufferMain, 0, customWidth * customHeight * sizeof(FragmentColor)); + memset(this->_3DFramebuffer16, 0, customWidth * customHeight * sizeof(u16)); + memset(this->_captureWorkingDisplay16, 0, customWidth * _gpuLargestDstLineCount * sizeof(u16)); + memset(this->_captureWorkingA16, 0, customWidth * _gpuLargestDstLineCount * sizeof(u16)); + memset(this->_captureWorkingB16, 0, customWidth * _gpuLargestDstLineCount * sizeof(u16)); + memset(this->_captureWorkingA32, 0, customWidth * _gpuLargestDstLineCount * sizeof(FragmentColor)); + memset(this->_captureWorkingB32, 0, customWidth * _gpuLargestDstLineCount * sizeof(FragmentColor)); memset(&this->_dispCapCnt, 0, sizeof(DISPCAPCNT_parsed)); this->_displayCaptureEnable = false; @@ -3489,15 +3486,6 @@ void GPUEngineA::Reset() this->ResetCaptureLineStates(1); this->ResetCaptureLineStates(2); this->ResetCaptureLineStates(3); - this->SetTargetDisplay( GPU->GetDisplayMain() ); - - memset(this->_3DFramebufferMain, 0, dispInfo.customWidth * dispInfo.customHeight * sizeof(FragmentColor)); - memset(this->_3DFramebuffer16, 0, dispInfo.customWidth * dispInfo.customHeight * sizeof(u16)); - memset(this->_captureWorkingDisplay16, 0, dispInfo.customWidth * _gpuLargestDstLineCount * sizeof(u16)); - memset(this->_captureWorkingA16, 0, dispInfo.customWidth * _gpuLargestDstLineCount * sizeof(u16)); - memset(this->_captureWorkingB16, 0, dispInfo.customWidth * _gpuLargestDstLineCount * sizeof(u16)); - memset(this->_captureWorkingA32, 0, dispInfo.customWidth * _gpuLargestDstLineCount * sizeof(FragmentColor)); - memset(this->_captureWorkingB32, 0, dispInfo.customWidth * _gpuLargestDstLineCount * sizeof(FragmentColor)); } void GPUEngineA::ResetCaptureLineStates(const size_t blockID) @@ -3593,10 +3581,9 @@ void GPUEngineA::AllocateWorkingBuffers(NDSColorFormat requestedColorFormat, siz this->_captureWorkingA32 = (FragmentColor *)malloc_alignedPage(w * _gpuLargestDstLineCount * sizeof(FragmentColor)); this->_captureWorkingB32 = (FragmentColor *)malloc_alignedPage(w * _gpuLargestDstLineCount * sizeof(FragmentColor)); - const NDSDisplayInfo &dispInfo = GPU->GetDisplayInfo(); const GPUEngineLineInfo &lineInfo = this->_currentCompositorInfo[GPU_VRAM_BLOCK_LINES].line; - if (dispInfo.colorFormat == NDSColorFormat_BGR888_Rev) + if (this->_targetDisplay->GetColorFormat() == NDSColorFormat_BGR888_Rev) { this->_VRAMCustomBlockPtr[0] = (FragmentColor *)GPU->GetCustomVRAMBuffer(); this->_VRAMCustomBlockPtr[1] = (FragmentColor *)this->_VRAMCustomBlockPtr[0] + (1 * lineInfo.indexCustom * w); @@ -4673,7 +4660,8 @@ void GPUEngineB::FinalizeAndDeallocate() void GPUEngineB::Reset() { - this->_Reset_Base(); + this->SetTargetDisplay( GPU->GetDisplayTouch() ); + this->GPUEngineBase::Reset(); this->_BGLayer[GPULayerID_BG0].BMPAddress = MMU_BBG; this->_BGLayer[GPULayerID_BG1].BMPAddress = MMU_BBG; @@ -4694,8 +4682,6 @@ void GPUEngineB::Reset() this->_BGLayer[GPULayerID_BG1].tileEntryAddress = MMU_BBG; this->_BGLayer[GPULayerID_BG2].tileEntryAddress = MMU_BBG; this->_BGLayer[GPULayerID_BG3].tileEntryAddress = MMU_BBG; - - this->SetTargetDisplay( GPU->GetDisplayTouch() ); } template @@ -4929,8 +4915,6 @@ void GPUSubsystem::Reset() this->_willFrameSkip = false; this->_videoFrameIndex = 0; this->_render3DFrameCount = 0; - this->_backlightIntensityTotal[NDSDisplayID_Main] = 0.0f; - this->_backlightIntensityTotal[NDSDisplayID_Touch] = 0.0f; this->ClearWithColor(0xFFFF); @@ -4959,6 +4943,9 @@ void GPUSubsystem::Reset() gfx3d_reset(); + this->_display[NDSDisplayID_Main]->SetBacklightIntensityTotal(0.0f); + this->_display[NDSDisplayID_Touch]->SetBacklightIntensityTotal(0.0f); + this->_display[NDSDisplayID_Main]->ClearAllLinesToNative(); this->_display[NDSDisplayID_Touch]->ClearAllLinesToNative(); @@ -5233,11 +5220,14 @@ void GPUSubsystem::SetCustomFramebufferSize(size_t w, size_t h) CurrentRenderer->RenderFinish(); CurrentRenderer->SetRenderNeedsFinish(false); + this->_display[NDSDisplayID_Main]->SetDisplaySize(w, h); + this->_display[NDSDisplayID_Touch]->SetDisplaySize(w, h); + this->_displayInfo.isCustomSizeRequested = ( (w != GPU_FRAMEBUFFER_NATIVE_WIDTH) || (h != GPU_FRAMEBUFFER_NATIVE_HEIGHT) ); this->_displayInfo.customWidth = w; this->_displayInfo.customHeight = h; - if (!this->_displayInfo.isCustomSizeRequested) + if (!this->_display[NDSDisplayID_Main]->IsCustomSizeRequested()) { this->_engineMain->ResetCaptureLineStates(0); this->_engineMain->ResetCaptureLineStates(1); @@ -5273,8 +5263,11 @@ void GPUSubsystem::SetColorFormat(const NDSColorFormat outputFormat) CurrentRenderer->RenderFinish(); CurrentRenderer->SetRenderNeedsFinish(false); - this->_displayInfo.colorFormat = outputFormat; - this->_displayInfo.pixelBytes = (outputFormat == NDSColorFormat_BGR555_Rev) ? sizeof(u16) : sizeof(FragmentColor); + this->_display[NDSDisplayID_Main]->SetColorFormat(outputFormat); + this->_display[NDSDisplayID_Touch]->SetColorFormat(outputFormat); + + this->_displayInfo.colorFormat = this->_display[NDSDisplayID_Main]->GetColorFormat(); + this->_displayInfo.pixelBytes = this->_display[NDSDisplayID_Main]->GetPixelBytes(); if (!this->_displayInfo.isCustomSizeRequested) { @@ -5446,9 +5439,9 @@ bool GPUSubsystem::Change3DRendererByID(int rendererID) return result; } - newRenderer->RequestColorFormat(GPU->GetDisplayInfo().colorFormat); + newRenderer->RequestColorFormat(this->_displayInfo.colorFormat); - Render3DError error = newRenderer->SetFramebufferSize(GPU->GetCustomFramebufferWidth(), GPU->GetCustomFramebufferHeight()); + Render3DError error = newRenderer->SetFramebufferSize(this->_displayInfo.customWidth, this->_displayInfo.customHeight); if (error != RENDER3DERROR_NOERR) { newRenderInterface->NDS_3D_Close(); @@ -5711,8 +5704,8 @@ void GPUSubsystem::RenderLine(const size_t l) this->_displayInfo.needConvertColorFormat[NDSDisplayID_Touch] = (OUTPUTFORMAT == NDSColorFormat_BGR666_Rev); // Set the average backlight intensity over 263 H-blanks. - this->_displayInfo.backlightIntensity[NDSDisplayID_Main] = this->_backlightIntensityTotal[NDSDisplayID_Main] / 263.0f; - this->_displayInfo.backlightIntensity[NDSDisplayID_Touch] = this->_backlightIntensityTotal[NDSDisplayID_Touch] / 263.0f; + this->_displayInfo.backlightIntensity[NDSDisplayID_Main] = this->_display[NDSDisplayID_Main]->GetBacklightIntensityTotal() / 263.0f; + this->_displayInfo.backlightIntensity[NDSDisplayID_Touch] = this->_display[NDSDisplayID_Touch]->GetBacklightIntensityTotal() / 263.0f; this->_engineMain->UpdateMasterBrightnessDisplayInfo(this->_displayInfo); this->_engineSub->UpdateMasterBrightnessDisplayInfo(this->_displayInfo); @@ -5733,8 +5726,8 @@ void GPUSubsystem::RenderLine(const size_t l) } // Reset the current backlight intensity total. - this->_backlightIntensityTotal[NDSDisplayID_Main] = 0.0f; - this->_backlightIntensityTotal[NDSDisplayID_Touch] = 0.0f; + this->_display[NDSDisplayID_Main]->SetBacklightIntensityTotal(0.0f); + this->_display[NDSDisplayID_Touch]->SetBacklightIntensityTotal(0.0f); if (this->_frameNeedsFinish) { @@ -5761,13 +5754,13 @@ void GPUSubsystem::UpdateAverageBacklightIntensityTotal() if (POWERMANCTL.MainBacklight_Enable != 0) { const BacklightLevel level = ((BACKLIGHTCTL.ExternalPowerState != 0) && (BACKLIGHTCTL.ForceMaxBrightnessWithExtPower_Enable != 0)) ? BacklightLevel_Maximum : (BacklightLevel)BACKLIGHTCTL.Level; - this->_backlightIntensityTotal[NDSDisplayID_Main] += backlightLevelToIntensityTable[level]; + this->_display[NDSDisplayID_Main]->SetBacklightIntensityTotal(this->_display[NDSDisplayID_Main]->GetBacklightIntensityTotal() + backlightLevelToIntensityTable[level]); } if (POWERMANCTL.TouchBacklight_Enable != 0) { const BacklightLevel level = ((BACKLIGHTCTL.ExternalPowerState != 0) && (BACKLIGHTCTL.ForceMaxBrightnessWithExtPower_Enable != 0)) ? BacklightLevel_Maximum : (BacklightLevel)BACKLIGHTCTL.Level; - this->_backlightIntensityTotal[NDSDisplayID_Touch] += backlightLevelToIntensityTable[level]; + this->_display[NDSDisplayID_Touch]->SetBacklightIntensityTotal(this->_display[NDSDisplayID_Touch]->GetBacklightIntensityTotal() + backlightLevelToIntensityTable[level]); } } @@ -5953,8 +5946,8 @@ void GPUSubsystem::SaveState(EMUFILE &os) os.write_32LE(this->_engineSub->savedBG3Y.value); // Version 2 - os.write_floatLE(_backlightIntensityTotal[NDSDisplayID_Main]); - os.write_floatLE(_backlightIntensityTotal[NDSDisplayID_Touch]); + os.write_floatLE( this->_display[NDSDisplayID_Main]->GetBacklightIntensityTotal() ); + os.write_floatLE( this->_display[NDSDisplayID_Touch]->GetBacklightIntensityTotal() ); } bool GPUSubsystem::LoadState(EMUFILE &is, int size) @@ -6004,23 +5997,28 @@ bool GPUSubsystem::LoadState(EMUFILE &is, int size) // Version 2 if (version >= 2) { - is.read_floatLE(this->_backlightIntensityTotal[NDSDisplayID_Main]); - is.read_floatLE(this->_backlightIntensityTotal[NDSDisplayID_Touch]); - this->_displayInfo.backlightIntensity[NDSDisplayID_Main] = this->_backlightIntensityTotal[NDSDisplayID_Main] / 71.0f; - this->_displayInfo.backlightIntensity[NDSDisplayID_Touch] = this->_backlightIntensityTotal[NDSDisplayID_Touch] / 71.0f; + float readIntensity = 0.0f; + + is.read_floatLE(readIntensity); + this->_display[NDSDisplayID_Main]->SetBacklightIntensityTotal(readIntensity / 71.0f); + this->_displayInfo.backlightIntensity[NDSDisplayID_Main] = this->_display[NDSDisplayID_Main]->GetBacklightIntensityTotal(); + + is.read_floatLE(readIntensity); + this->_display[NDSDisplayID_Touch]->SetBacklightIntensityTotal(readIntensity / 71.0f); + this->_displayInfo.backlightIntensity[NDSDisplayID_Touch] = this->_display[NDSDisplayID_Touch]->GetBacklightIntensityTotal(); } else { // UpdateAverageBacklightIntensityTotal() adds to _backlightIntensityTotal, and is called 263 times per frame. // Of these, 71 calls are after _displayInfo.backlightIntensity is set. // This emulates those calls as a way of guessing what the backlight values were in a savestate which doesn't contain that information. - this->_backlightIntensityTotal[0] = 0.0f; - this->_backlightIntensityTotal[1] = 0.0f; + this->_display[NDSDisplayID_Main]->SetBacklightIntensityTotal(0.0f); + this->_display[NDSDisplayID_Touch]->SetBacklightIntensityTotal(0.0f); this->UpdateAverageBacklightIntensityTotal(); - this->_displayInfo.backlightIntensity[0] = this->_backlightIntensityTotal[0]; - this->_displayInfo.backlightIntensity[1] = this->_backlightIntensityTotal[1]; - this->_backlightIntensityTotal[0] *= 71; - this->_backlightIntensityTotal[1] *= 71; + this->_displayInfo.backlightIntensity[NDSDisplayID_Main] = this->_display[NDSDisplayID_Main]->GetBacklightIntensityTotal(); + this->_displayInfo.backlightIntensity[NDSDisplayID_Touch] = this->_display[NDSDisplayID_Touch]->GetBacklightIntensityTotal(); + this->_display[NDSDisplayID_Main]->SetBacklightIntensityTotal(this->_display[NDSDisplayID_Main]->GetBacklightIntensityTotal() * 71.0f); + this->_display[NDSDisplayID_Touch]->SetBacklightIntensityTotal(this->_display[NDSDisplayID_Touch]->GetBacklightIntensityTotal() * 71.0f); } // Parse all GPU engine related registers based on a previously read MMU savestate chunk. @@ -6178,6 +6176,13 @@ void NDSDisplay::__constructor(const NDSDisplayID displayID, GPUEngineBase *theE _nativeBuffer16 = NULL; _customBuffer = NULL; + + _customColorFormat = NDSColorFormat_BGR555_Rev; + _customPixelBytes = sizeof(u16); + _customWidth = GPU_FRAMEBUFFER_NATIVE_WIDTH; + _customHeight = GPU_FRAMEBUFFER_NATIVE_HEIGHT; + _isCustomSizeRequested = false; + _renderedBuffer = this->_nativeBuffer16; _renderedWidth = GPU_FRAMEBUFFER_NATIVE_WIDTH; _renderedHeight = GPU_FRAMEBUFFER_NATIVE_HEIGHT; @@ -6253,16 +6258,14 @@ void NDSDisplay::ClearAllLinesToNative() template void NDSDisplay::ResolveLinesDisplayedNative() { - const NDSDisplayInfo &dispInfo = GPU->GetDisplayInfo(); - if (this->_nativeLineDisplayCount == GPU_FRAMEBUFFER_NATIVE_HEIGHT) { return; } else if (this->_nativeLineDisplayCount == 0) { - this->_renderedWidth = dispInfo.customWidth; - this->_renderedHeight = dispInfo.customHeight; + this->_renderedWidth = this->_customWidth; + this->_renderedHeight = this->_customHeight; this->_renderedBuffer = this->_customBuffer; return; } @@ -6321,8 +6324,8 @@ void NDSDisplay::ResolveLinesDisplayedNative() } this->_nativeLineDisplayCount = 0; - this->_renderedWidth = dispInfo.customWidth; - this->_renderedHeight = dispInfo.customHeight; + this->_renderedWidth = this->_customWidth; + this->_renderedHeight = this->_customHeight; this->_renderedBuffer = this->_customBuffer; } @@ -6430,6 +6433,44 @@ void NDSDisplay::SetDrawBuffers(u16 *nativeBuffer16, u32 *workingNativeBuffer32, } } +NDSColorFormat NDSDisplay::GetColorFormat() const +{ + return this->_customColorFormat; +} + +void NDSDisplay::SetColorFormat(NDSColorFormat colorFormat) +{ + this->_customColorFormat = colorFormat; + this->_customPixelBytes = (colorFormat == NDSColorFormat_BGR555_Rev) ? sizeof(u16) : sizeof(FragmentColor); +} + +size_t NDSDisplay::GetPixelBytes() const +{ + return this->_customPixelBytes; +} + +size_t NDSDisplay::GetWidth() const +{ + return this->_customWidth; +} + +size_t NDSDisplay::GetHeight() const +{ + return this->_customHeight; +} + +void NDSDisplay::SetDisplaySize(size_t w, size_t h) +{ + this->_customWidth = w; + this->_customHeight = h; + this->_isCustomSizeRequested = (this->_customWidth != GPU_FRAMEBUFFER_NATIVE_WIDTH) || (this->_customHeight != GPU_FRAMEBUFFER_NATIVE_HEIGHT); +} + +bool NDSDisplay::IsCustomSizeRequested() const +{ + return this->_isCustomSizeRequested; +} + void* NDSDisplay::GetRenderedBuffer() const { return this->_renderedBuffer; @@ -6445,6 +6486,16 @@ size_t NDSDisplay::GetRenderedHeight() const return this->_renderedHeight; } +float NDSDisplay::GetBacklightIntensityTotal() const +{ + return this->_backlightIntensityTotal; +} + +void NDSDisplay::SetBacklightIntensityTotal(float intensity) +{ + this->_backlightIntensityTotal = intensity; +} + template void GPUEngineBase::ParseReg_BGnHOFS(); template void GPUEngineBase::ParseReg_BGnHOFS(); template void GPUEngineBase::ParseReg_BGnHOFS(); diff --git a/desmume/src/GPU.h b/desmume/src/GPU.h index 759b4cd26..1a01ab37f 100644 --- a/desmume/src/GPU.h +++ b/desmume/src/GPU.h @@ -1144,19 +1144,20 @@ typedef struct // Changed by calling GPUSubsystem::SetColorFormat(). NDSColorFormat colorFormat; // The output color format. - size_t pixelBytes; // The number of bytes per pixel. + u32 pixelBytes; // The number of bytes per pixel. // Changed by calling GPUSubsystem::SetFramebufferSize(). bool isCustomSizeRequested; // Reports that the call to GPUSubsystem::SetFramebufferSize() resulted in a custom rendering size. // true - The user requested a custom size. // 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 framebufferPageSize; // The size of a single framebuffer page, which includes the native and custom buffers of both + u32 customWidth; // The requested custom width, measured in pixels. + u32 customHeight; // The requested custom height, measured in pixels. + u32 framebufferPageSize; // The size of a single framebuffer page, which includes the native and custom buffers of both // displays, measured in bytes. // Changed by calling GPUSubsystem::SetColorFormat() or GPUSubsystem::SetFramebufferSize(). - size_t framebufferPageCount; // The number of framebuffer pages that were requested by the client. + u32 framebufferPageCount; // The number of framebuffer pages that were requested by the client. The maximum number of pages + // is MAX_FRAMEBUFFER_PAGES. void *masterFramebufferHead; // Pointer to the head of the master framebuffer memory block that encompasses all buffers. // Changed by calling GPUEngineBase::SetEnableState(). @@ -1168,26 +1169,33 @@ typedef struct u8 bufferIndex; // Index of a specific framebuffer page for the GPU emulation to write data into. // Indexing starts at 0, and must be less than framebufferPageCount. // A specific index can be chosen at the DidFrameBegin event. - size_t sequenceNumber; // A unique number assigned to each frame that increments for each DidFrameEnd event. Never resets. + u64 sequenceNumber; // A unique number assigned to each frame that increments for each DidFrameEnd event. Never resets. - u16 *masterNativeBuffer16; // Pointer to the head of the master native buffer. + u16 *masterNativeBuffer16; // Pointer to the head of the master native-sized 16-bit buffer. void *masterCustomBuffer; // Pointer to the head of the master custom buffer. // If GPUSubsystem::GetWillAutoResolveToCustomBuffer() would return true, or if // GPUSubsystem::ResolveDisplayToCustomFramebuffer() is called, then this buffer is used as the - // target buffer for resolving any native-sized renders. + // target buffer for resolving any native-sized 16-bit renders. - u16 *nativeBuffer16[2]; // Pointer to the display's native size framebuffer. - void *customBuffer[2]; // Pointer to the display's custom size framebuffer. + u16 *nativeBuffer16[2]; // Pointer to the display's native-size 16-bit framebuffer. + void *customBuffer[2]; // Pointer to the display's custom framebuffer. Used whenever the framebuffer is not native-sized + // or when the requested color format is not 15-bit. - 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. + u32 renderedWidth[2]; // The display rendered at this width, measured in pixels. + u32 renderedHeight[2]; // The display rendered at this height, measured in pixels. void *renderedBuffer[2]; // The display rendered to this buffer. GPUEngineID engineID[2]; // ID of the engine sourcing the display. + // Technically, NDS displays shouldn't be associated with a single GPU engine since it's possible for + // a single display to associate with both. But for the sake of compatibility with how clients use + // TCommonSettings.showGpu to show/hide displays, the engineID member must be present here. - 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. + bool didPerformCustomRender[2]; // Reports that the display rendered to the custom buffer. Rendering to the custom buffers is the + // default behavior, but can be turned off by calling GPUSubsystem::SetWillAutoResolveToCustomBuffer() + // and passing 'false'. However, rendering to the custom buffers can be forced at any time by calling + // GPUSubsystem::ResolveDisplayToCustomFramebuffer(). + // true - The display rendered to the custom buffer. + // false - The display rendered to the native-size 16-bit buffer only. 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 @@ -1399,7 +1407,7 @@ protected: itemsForPriority_t _itemsForPriority[NB_PRIORITIES]; struct MosaicColor { - CACHE_ALIGN u16 bg[4][GPU_FRAMEBUFFER_NATIVE_WIDTH + sizeof(u32)]; // Pad this buffersa little bit to avoid buffer overruns with vectorized gather instructions. + CACHE_ALIGN u16 bg[4][GPU_FRAMEBUFFER_NATIVE_WIDTH + sizeof(u32)]; // Pad this buffer a little bit to avoid buffer overruns with vectorized gather instructions. struct Obj { u16 color; u8 alpha; @@ -1438,7 +1446,6 @@ protected: FragmentColor _asyncClearBackdropColor32; // Do not modify this variable directly. bool _asyncClearUseInternalCustomBuffer; // Do not modify this variable directly. - void _Reset_Base(); void _ResortBGLayers(); template void _TransitionLineNativeToCustom(GPUEngineCompositorInfo &compInfo); @@ -1713,10 +1720,18 @@ private: u32 *_workingNativeBuffer32; void *_customBuffer; + NDSColorFormat _customColorFormat; + size_t _customPixelBytes; + size_t _customWidth; + size_t _customHeight; + bool _isCustomSizeRequested; + void *_renderedBuffer; size_t _renderedWidth; size_t _renderedHeight; + float _backlightIntensityTotal; + void __constructor(const NDSDisplayID displayID, GPUEngineBase *theEngine); public: @@ -1745,9 +1760,21 @@ public: void* GetCustomBuffer() const; void SetDrawBuffers(u16 *nativeBuffer16, u32 *workingNativeBuffer32, void *customBuffer); + NDSColorFormat GetColorFormat() const; + void SetColorFormat(NDSColorFormat colorFormat); + + size_t GetPixelBytes() const; + size_t GetWidth() const; + size_t GetHeight() const; + void SetDisplaySize(size_t w, size_t h); + bool IsCustomSizeRequested() const; + void* GetRenderedBuffer() const; size_t GetRenderedWidth() const; size_t GetRenderedHeight() const; + + float GetBacklightIntensityTotal() const; + void SetBacklightIntensityTotal(float intensity); }; class GPUEventHandler @@ -1788,7 +1815,6 @@ private: GPUEngineA *_engineMain; GPUEngineB *_engineSub; NDSDisplay *_display[2]; - float _backlightIntensityTotal[2]; GPUEngineLineInfo _lineInfo[GPU_VRAM_BLOCK_LINES + 1]; Task *_asyncEngineBufferSetupTask;