From a8c8a8665bc12dceb60e56de52806faeb001f16d Mon Sep 17 00:00:00 2001 From: rogerman Date: Sun, 27 Nov 2016 16:10:00 -0800 Subject: [PATCH] SoftRasterizer: Texture deposterization and upscaling are now supported with this renderer. --- desmume/src/rasterize.cpp | 180 ++++++++++++++++++++++++++++++++++++-- desmume/src/rasterize.h | 21 ++++- desmume/src/render3D.cpp | 7 +- desmume/src/render3D.h | 1 + 4 files changed, 198 insertions(+), 11 deletions(-) diff --git a/desmume/src/rasterize.cpp b/desmume/src/rasterize.cpp index 138851d60..a34040b41 100644 --- a/desmume/src/rasterize.cpp +++ b/desmume/src/rasterize.cpp @@ -55,6 +55,8 @@ #include "MMU.h" #include "NDSSystem.h" #include "utils/task.h" +#include "filter/filter.h" +#include "filter/xbrz.h" //#undef FORCEINLINE //#define FORCEINLINE @@ -444,8 +446,8 @@ public: if (!CommonSettings.GFX3D_TXTHack) { - iu = s32floor(u); - iv = s32floor(v); + iu = s32floor(u * (float)lastTexKey->GetRenderWidth() / (float)lastTexKey->GetWidth()); + iv = s32floor(v * (float)lastTexKey->GetRenderHeight() / (float)lastTexKey->GetHeight()); } else { @@ -455,7 +457,7 @@ public: sampler.dowrap(iu, iv); FragmentColor color; - const u32 *textureData = lastTexKey->GetUnpackData(); + const u32 *textureData = lastTexKey->GetRenderData(); color.color = textureData[( iv << lastTexKey->GetRenderWidthShift() ) + iu]; @@ -1150,13 +1152,26 @@ SoftRasterizerTexture::SoftRasterizerTexture(u32 texAttributes, u32 palAttribute { _cacheSize = GetUnpackSizeUsingFormat(TexFormat_15bpp); _unpackData = (u32 *)malloc_alignedCacheLine(_cacheSize); + + _useDeposterize = false; + _scalingFactor = 1; + _customBuffer = NULL; + + _renderData = _unpackData; _renderWidth = _sizeS; _renderHeight = _sizeT; _renderWidthMask = _renderWidth - 1; _renderHeightMask = _renderHeight - 1; - _renderWidthShift = 0; + memset(&_deposterizeSrcSurface, 0, sizeof(_deposterizeSrcSurface)); + memset(&_deposterizeDstSurface, 0, sizeof(_deposterizeDstSurface)); + + _deposterizeSrcSurface.Width = _deposterizeDstSurface.Width = _sizeS; + _deposterizeSrcSurface.Height = _deposterizeDstSurface.Height = _sizeT; + _deposterizeSrcSurface.Pitch = _deposterizeDstSurface.Pitch = 1; + _deposterizeSrcSurface.Surface = (unsigned char *)_unpackData; + u32 tempWidth = _renderWidth; while ( (tempWidth & 1) == 0) { @@ -1168,11 +1183,61 @@ SoftRasterizerTexture::SoftRasterizerTexture(u32 texAttributes, u32 palAttribute SoftRasterizerTexture::~SoftRasterizerTexture() { free_aligned(this->_unpackData); + free_aligned(this->_deposterizeDstSurface.Surface); + free_aligned(this->_customBuffer); } -void SoftRasterizerTexture::Load(void *targetBuffer) +template +void SoftRasterizerTexture::_Upscale() { - this->Unpack((u32 *)targetBuffer); + if ( (SCALEFACTOR != 2) && (SCALEFACTOR != 4) ) + { + return; + } + + u32 *src = (this->_useDeposterize) ? (u32 *)this->_deposterizeDstSurface.Surface : this->_unpackData; + + if (this->_packFormat == TEXMODE_A3I5 || this->_packFormat == TEXMODE_A5I3) + { + xbrz::scale(src, this->_customBuffer, this->_sizeS, this->_sizeT); + } + else + { + xbrz::scale(src, this->_customBuffer, this->_sizeS, this->_sizeT); + } +} + +void SoftRasterizerTexture::Load() +{ + if (this->_scalingFactor == 1 && !this->_useDeposterize) + { + this->Unpack((u32 *)this->_renderData); + } + else + { + this->Unpack((u32 *)this->_unpackData); + + if (this->_useDeposterize) + { + RenderDeposterize(this->_deposterizeSrcSurface, this->_deposterizeDstSurface); + } + + switch (this->_scalingFactor) + { + case 2: + this->_Upscale<2>(); + break; + + case 4: + this->_Upscale<4>(); + break; + + default: + break; + } + + ColorspaceConvertBuffer8888To6665(this->_renderData, this->_renderData, this->_renderWidth * this->_renderHeight); + } } u32* SoftRasterizerTexture::GetUnpackData() @@ -1180,6 +1245,11 @@ u32* SoftRasterizerTexture::GetUnpackData() return this->_unpackData; } +u32* SoftRasterizerTexture::GetRenderData() +{ + return this->_renderData; +} + u32 SoftRasterizerTexture::GetRenderWidth() const { return this->_renderWidth; @@ -1205,6 +1275,96 @@ u32 SoftRasterizerTexture::GetRenderWidthShift() const return this->_renderWidthShift; } +bool SoftRasterizerTexture::IsUsingDeposterize() const +{ + return this->_useDeposterize; +} + +void SoftRasterizerTexture::SetUseDeposterize(bool willDeposterize) +{ + this->_useDeposterize = willDeposterize; + + if ( (this->_deposterizeDstSurface.Surface == NULL) && willDeposterize ) + { + this->_deposterizeDstSurface.Surface = (unsigned char *)malloc_alignedCacheLine(this->_cacheSize * 2); + this->_deposterizeDstSurface.workingSurface[0] = this->_deposterizeDstSurface.Surface + this->_cacheSize; + } + else if ( (this->_deposterizeDstSurface.Surface != NULL) && !willDeposterize ) + { + free_aligned(this->_deposterizeDstSurface.Surface); + this->_deposterizeDstSurface.Surface = NULL; + } + + if (this->_scalingFactor == 1) + { + if (this->_useDeposterize) + { + this->_renderData = (u32 *)this->_deposterizeDstSurface.Surface; + } + else + { + this->_renderData = this->_unpackData; + } + } + else + { + this->_renderData = this->_customBuffer; + } +} + +size_t SoftRasterizerTexture::GetScalingFactor() const +{ + return this->_scalingFactor; +} + +void SoftRasterizerTexture::SetScalingFactor(size_t scalingFactor) +{ + if ( (scalingFactor != 2) && (scalingFactor != 4) ) + { + scalingFactor = 1; + } + + u32 newWidth = this->_sizeS * scalingFactor; + u32 newHeight = this->_sizeT * scalingFactor; + + if (this->_renderWidth != newWidth || this->_renderHeight != newHeight) + { + u32 *oldBuffer = this->_customBuffer; + this->_customBuffer = (u32 *)malloc_alignedCacheLine(newWidth * newHeight * sizeof(u32)); + free_aligned(oldBuffer); + } + + this->_scalingFactor = scalingFactor; + this->_renderWidth = newWidth; + this->_renderHeight = newHeight; + this->_renderWidthMask = newWidth - 1; + this->_renderHeightMask = newHeight - 1; + this->_renderWidthShift = 0; + + u32 tempWidth = newWidth; + while ( (tempWidth & 1) == 0) + { + tempWidth >>= 1; + this->_renderWidthShift++; + } + + if (this->_scalingFactor == 1) + { + if (this->_useDeposterize) + { + this->_renderData = (u32 *)this->_deposterizeDstSurface.Surface; + } + else + { + this->_renderData = this->_unpackData; + } + } + else + { + this->_renderData = this->_customBuffer; + } +} + GPU3DInterface gpu3DRasterize = { "SoftRasterizer", SoftRasterizerRendererCreate, @@ -1441,7 +1601,9 @@ void SoftRasterizerRenderer::setupTextures() if (lastTexItem->IsLoadNeeded()) { - lastTexItem->Load(lastTexItem->GetUnpackData()); + lastTexItem->SetUseDeposterize(this->_textureDeposterize); + lastTexItem->SetScalingFactor(this->_textureScalingFactor); + lastTexItem->Load(); } for (size_t i = 0; i < this->_clippedPolyCount; i++) @@ -1464,7 +1626,9 @@ void SoftRasterizerRenderer::setupTextures() if (lastTexItem->IsLoadNeeded()) { - lastTexItem->Load(lastTexItem->GetUnpackData()); + lastTexItem->SetUseDeposterize(this->_textureDeposterize); + lastTexItem->SetScalingFactor(this->_textureScalingFactor); + lastTexItem->Load(); } lastTexParams = thePoly.texParam; diff --git a/desmume/src/rasterize.h b/desmume/src/rasterize.h index 8629b85bb..adc8794ea 100644 --- a/desmume/src/rasterize.h +++ b/desmume/src/rasterize.h @@ -44,24 +44,43 @@ class SoftRasterizerTexture : public TextureStore { protected: u32 *_unpackData; + + u32 *_renderData; u32 _renderWidth; u32 _renderHeight; u32 _renderWidthMask; u32 _renderHeightMask; u32 _renderWidthShift; + bool _useDeposterize; + size_t _scalingFactor; + u32 *_customBuffer; + + SSurface _deposterizeSrcSurface; + SSurface _deposterizeDstSurface; + + template void _Upscale(); + public: SoftRasterizerTexture(u32 texAttributes, u32 palAttributes); virtual ~SoftRasterizerTexture(); - virtual void Load(void *targetBuffer); + virtual void Load(); u32* GetUnpackData(); + + u32* GetRenderData(); u32 GetRenderWidth() const; u32 GetRenderHeight() const; u32 GetRenderWidthMask() const; u32 GetRenderHeightMask() const; u32 GetRenderWidthShift() const; + + bool IsUsingDeposterize() const; + void SetUseDeposterize(bool willDeposterize); + + size_t GetScalingFactor() const; + void SetScalingFactor(size_t scalingFactor); }; #if defined(ENABLE_SSE2) diff --git a/desmume/src/render3D.cpp b/desmume/src/render3D.cpp index 8d63b1edd..faa8cbd4e 100644 --- a/desmume/src/render3D.cpp +++ b/desmume/src/render3D.cpp @@ -234,6 +234,7 @@ Render3D::Render3D() _willFlushFramebufferRGBA5551 = true; _textureScalingFactor = 1; + _textureDeposterize = false; _textureSmooth = false; _textureUpscaleBuffer = NULL; @@ -346,7 +347,7 @@ void Render3D::SetTextureProcessingProperties(size_t scalingFactor, bool willDep const size_t newScalingFactor = (isScaleValid) ? scalingFactor : 1; bool needTexCacheReset = false; - if ( willDeposterize && (this->_textureDeposterizeDstSurface.Surface == NULL) ) + if ( willDeposterize && !this->_textureDeposterize) { // 1024x1024 texels is the largest possible texture size. // We need two buffers, one for each deposterize stage. @@ -357,14 +358,16 @@ void Render3D::SetTextureProcessingProperties(size_t scalingFactor, bool willDep memset(this->_textureDeposterizeDstSurface.Surface, 0, bufferSize); + this->_textureDeposterize = true; needTexCacheReset = true; } - else if ( !willDeposterize && (this->_textureDeposterizeDstSurface.Surface != NULL) ) + else if (!willDeposterize && this->_textureDeposterize) { free_aligned(this->_textureDeposterizeDstSurface.Surface); this->_textureDeposterizeDstSurface.Surface = NULL; this->_textureDeposterizeDstSurface.workingSurface[0] = NULL; + this->_textureDeposterize = false; needTexCacheReset = true; } diff --git a/desmume/src/render3D.h b/desmume/src/render3D.h index 3ffd0df61..6774b64e0 100644 --- a/desmume/src/render3D.h +++ b/desmume/src/render3D.h @@ -130,6 +130,7 @@ protected: bool _willFlushFramebufferRGBA5551; size_t _textureScalingFactor; + bool _textureDeposterize; bool _textureSmooth; SSurface _textureDeposterizeSrcSurface;