From 4d8e8e7741901637954cb882e4de4e041b8577d3 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 15 Dec 2018 00:38:27 +0100 Subject: [PATCH] - enable the texture scalers in software mode. Currently only implemented for 8 bit in the classic renderer. --- src/swrenderer/line/r_line.cpp | 12 +-- src/swrenderer/textures/r_swtexture.cpp | 40 +++++++- src/swrenderer/textures/r_swtexture.h | 32 +++--- src/textures/hires/hqresize.cpp | 128 ++++++++++++------------ src/textures/textures.h | 1 + 5 files changed, 126 insertions(+), 87 deletions(-) diff --git a/src/swrenderer/line/r_line.cpp b/src/swrenderer/line/r_line.cpp index 9083f9ec4..11ce9dc19 100644 --- a/src/swrenderer/line/r_line.cpp +++ b/src/swrenderer/line/r_line.cpp @@ -858,7 +858,7 @@ namespace swrenderer } else { - mTopPart.TextureMid += rowoffset; + mTopPart.TextureMid += rowoffset * mTopPart.Texture->GetPhysicalScale(); } } @@ -918,7 +918,7 @@ namespace swrenderer { // rowoffset is added outside the multiply so that it positions the texture // by texels instead of world units. - mMiddlePart.TextureMid += rowoffset; + mMiddlePart.TextureMid += rowoffset * mMiddlePart.Texture->GetPhysicalScale(); } } @@ -983,7 +983,7 @@ namespace swrenderer } else { - mBottomPart.TextureMid += rowoffset; + mBottomPart.TextureMid += rowoffset * mBottomPart.Texture->GetPhysicalScale(); } } @@ -1158,7 +1158,7 @@ namespace swrenderer } else { - offset = mTopPart.TextureOffsetU; + offset = mTopPart.TextureOffsetU * mTopPart.Texture->GetPhysicalScale(); } if (xscale < 0) { @@ -1205,7 +1205,7 @@ namespace swrenderer } else { - offset = mMiddlePart.TextureOffsetU; + offset = mMiddlePart.TextureOffsetU * mMiddlePart.Texture->GetPhysicalScale(); } if (xscale < 0) { @@ -1253,7 +1253,7 @@ namespace swrenderer } else { - offset = mBottomPart.TextureOffsetU; + offset = mBottomPart.TextureOffsetU * mBottomPart.Texture->GetPhysicalScale(); } if (xscale < 0) { diff --git a/src/swrenderer/textures/r_swtexture.cpp b/src/swrenderer/textures/r_swtexture.cpp index 100825252..43d6405b2 100644 --- a/src/swrenderer/textures/r_swtexture.cpp +++ b/src/swrenderer/textures/r_swtexture.cpp @@ -37,6 +37,9 @@ #include "r_swtexture.h" #include "bitmap.h" #include "m_alloc.h" +#include "imagehelpers.h" + +EXTERN_CVAR(Bool, gl_texture_usehires) FSoftwareTexture *FTexture::GetSoftwareTexture() @@ -56,6 +59,25 @@ FSoftwareTexture *FTexture::GetSoftwareTexture() // //========================================================================== +FSoftwareTexture::FSoftwareTexture(FTexture *tex) +{ + mTexture = tex; + mSource = tex; + + mBufferFlags = (gl_texture_usehires && !tex->isScaled() && tex->GetImage() && !tex->isSprite() ) ? CTF_CheckHires|CTF_ProcessData : CTF_ProcessData; + auto info = tex->CreateTexBuffer(0, CTF_CheckOnly| mBufferFlags); + mPhysicalWidth = info.mWidth; + mPhysicalHeight = info.mHeight; + mPhysicalScale = mPhysicalWidth / tex->Width;; + CalcBitSize(); +} + +//========================================================================== +// +// +// +//========================================================================== + void FSoftwareTexture::CalcBitSize () { // WidthBits is rounded down, and HeightBits is rounded up @@ -93,7 +115,23 @@ const uint8_t *FSoftwareTexture::GetPixels(int style) { if (Pixels.Size() == 0 || CheckModified(style)) { - Pixels = mSource->Get8BitPixels(style); + if (mPhysicalScale == 1) + { + Pixels = mSource->Get8BitPixels(style); + } + else + { + auto tempbuffer = mTexture->CreateTexBuffer(0, mBufferFlags); + Pixels.Resize(GetWidth()*GetHeight()); + PalEntry *pe = (PalEntry*)tempbuffer.mBuffer; + for (int y = 0; y < GetHeight(); y++) + { + for (int x = 0; x < GetWidth(); x++) + { + Pixels[y + x * GetHeight()] = ImageHelpers::RGBToPalette(false, pe[x + y * GetWidth()], true); + } + } + } } return Pixels.Data(); } diff --git a/src/swrenderer/textures/r_swtexture.h b/src/swrenderer/textures/r_swtexture.h index 14810b071..97729e2c6 100644 --- a/src/swrenderer/textures/r_swtexture.h +++ b/src/swrenderer/textures/r_swtexture.h @@ -21,19 +21,17 @@ protected: FSoftwareTextureSpan **Spandata[3] = { }; uint8_t WidthBits = 0, HeightBits = 0; uint16_t WidthMask = 0; - + int mPhysicalWidth, mPhysicalHeight; + int mPhysicalScale; + int mBufferFlags; + void FreeAllSpans(); template FSoftwareTextureSpan **CreateSpans(const T *pixels); void FreeSpans(FSoftwareTextureSpan **spans); void CalcBitSize(); public: - FSoftwareTexture(FTexture *tex) - { - mTexture = tex; - mSource = tex; - CalcBitSize(); - } + FSoftwareTexture(FTexture *tex); virtual ~FSoftwareTexture() { @@ -59,8 +57,8 @@ public: int GetSkyOffset() const { return mTexture->GetSkyOffset(); } PalEntry GetSkyCapColor(bool bottom) const { return mTexture->GetSkyCapColor(bottom); } - int GetWidth () { return mTexture->GetWidth(); } - int GetHeight () { return mTexture->GetHeight(); } + int GetWidth () { return mPhysicalWidth; } + int GetHeight () { return mPhysicalHeight; } int GetWidthBits() { return WidthBits; } int GetHeightBits() { return HeightBits; } @@ -68,15 +66,14 @@ public: int GetScaledHeight () { return mTexture->GetScaledHeight(); } double GetScaledWidthDouble () { return mTexture->GetScaledWidthDouble(); } double GetScaledHeightDouble () { return mTexture->GetScaledHeightDouble(); } - double GetScaleY() const { return mTexture->GetScaleY(); } // Now with improved offset adjustment. - int GetLeftOffset(int adjusted) { return mTexture->GetLeftOffset(adjusted); } - int GetTopOffset(int adjusted) { return mTexture->GetTopOffset(adjusted); } - int GetScaledLeftOffset (int adjusted) { return mTexture->GetScaledLeftOffset(adjusted); } - int GetScaledTopOffset (int adjusted) { return mTexture->GetScaledTopOffset(adjusted); } - double GetScaledLeftOffsetDouble(int adjusted) { return mTexture->GetScaledLeftOffsetDouble(adjusted); } - double GetScaledTopOffsetDouble(int adjusted) { return mTexture->GetScaledTopOffsetDouble(adjusted); } + int GetLeftOffset(int adjusted) { return mTexture->GetLeftOffset(adjusted) * mPhysicalScale; } + int GetTopOffset(int adjusted) { return mTexture->GetTopOffset(adjusted) * mPhysicalScale; } + int GetScaledLeftOffset (int adjusted) { return mTexture->GetScaledLeftOffset(adjusted) * mPhysicalScale; } + int GetScaledTopOffset (int adjusted) { return mTexture->GetScaledTopOffset(adjusted) * mPhysicalScale; } + double GetScaledLeftOffsetDouble(int adjusted) { return mTexture->GetScaledLeftOffsetDouble(adjusted) * mPhysicalScale; } + double GetScaledTopOffsetDouble(int adjusted) { return mTexture->GetScaledTopOffsetDouble(adjusted) * mPhysicalScale; } // Interfaces for the different renderers. Everything that needs to check renderer-dependent offsets // should use these, so that if changes are needed, this is the only place to edit. @@ -93,7 +90,8 @@ public: int GetScaledLeftOffsetPo() { return GetScaledLeftOffset(r_spriteadjustSW); } int GetScaledTopOffsetPo() { return GetScaledTopOffset(r_spriteadjustSW); } - DVector2 GetScale() const { return mTexture->Scale; } + DVector2 GetScale() const { return mTexture->Scale * mPhysicalScale; } + int GetPhysicalScale() const { return mPhysicalScale; } virtual void Unload() { diff --git a/src/textures/hires/hqresize.cpp b/src/textures/hires/hqresize.cpp index e6acb4911..82a4d8817 100644 --- a/src/textures/hires/hqresize.cpp +++ b/src/textures/hires/hqresize.cpp @@ -387,69 +387,71 @@ void FTexture::CreateUpsampledTextureBuffer(FTextureBuffer &texbuffer, bool hasA break; } - if (texbuffer.mBuffer) + int type = gl_texture_hqresizemode; + int mult = gl_texture_hqresizemult; +#ifdef HAVE_MMX + // hqNx MMX does not preserve the alpha channel so fall back to C-version for such textures + if (hasAlpha && type == 3) { - int type = gl_texture_hqresizemode; - int mult = gl_texture_hqresizemult; -#ifdef HAVE_MMX - // hqNx MMX does not preserve the alpha channel so fall back to C-version for such textures - if (hasAlpha && type == 3) - { - type = 2; - } -#endif - // These checks are to ensure consistency of the content ID. - if (mult < 2 || mult > 6 || type < 1 || type > 6) return; - if (type < 4 && mult > 4) mult = 4; - - if (!checkonly) - { - if (type == 1) - { - if (mult == 2) - texbuffer.mBuffer = scaleNxHelper(&scale2x, 2, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); - else if (mult == 3) - texbuffer.mBuffer = scaleNxHelper(&scale3x, 3, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); - else if (mult == 4) - texbuffer.mBuffer = scaleNxHelper(&scale4x, 4, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); - else return; - } - else if (type == 2) - { - if (mult == 2) - texbuffer.mBuffer = hqNxHelper(&hq2x_32, 2, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); - else if (mult == 3) - texbuffer.mBuffer = hqNxHelper(&hq3x_32, 3, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); - else if (mult == 4) - texbuffer.mBuffer = hqNxHelper(&hq4x_32, 4, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); - else return; - } -#ifdef HAVE_MMX - else if (type == 3) - { - if (mult == 2) - texbuffer.mBuffer = hqNxAsmHelper(&HQnX_asm::hq2x_32, 2, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); - else if (mult == 3) - texbuffer.mBuffer = hqNxAsmHelper(&HQnX_asm::hq3x_32, 3, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); - else if (mult == 4) - texbuffer.mBuffer = hqNxAsmHelper(&HQnX_asm::hq4x_32, 4, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); - else return; - } -#endif - else if (type == 4) - texbuffer.mBuffer = xbrzHelper(xbrz::scale, mult, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); - else if (type == 5) - texbuffer.mBuffer = xbrzHelper(xbrzOldScale, mult, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); - else if (type == 6) - texbuffer.mBuffer = normalNxHelper(&normalNx, mult, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); - else - return; - } - // Encode the scaling method in the content ID. - FContentIdBuilder contentId; - contentId.id = texbuffer.mContentId; - contentId.scaler = type; - contentId.scalefactor = mult; - texbuffer.mContentId = contentId.id; + type = 2; } +#endif + // These checks are to ensure consistency of the content ID. + if (mult < 2 || mult > 6 || type < 1 || type > 6) return; + if (type < 4 && mult > 4) mult = 4; + + if (!checkonly) + { + if (type == 1) + { + if (mult == 2) + texbuffer.mBuffer = scaleNxHelper(&scale2x, 2, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); + else if (mult == 3) + texbuffer.mBuffer = scaleNxHelper(&scale3x, 3, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); + else if (mult == 4) + texbuffer.mBuffer = scaleNxHelper(&scale4x, 4, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); + else return; + } + else if (type == 2) + { + if (mult == 2) + texbuffer.mBuffer = hqNxHelper(&hq2x_32, 2, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); + else if (mult == 3) + texbuffer.mBuffer = hqNxHelper(&hq3x_32, 3, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); + else if (mult == 4) + texbuffer.mBuffer = hqNxHelper(&hq4x_32, 4, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); + else return; + } +#ifdef HAVE_MMX + else if (type == 3) + { + if (mult == 2) + texbuffer.mBuffer = hqNxAsmHelper(&HQnX_asm::hq2x_32, 2, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); + else if (mult == 3) + texbuffer.mBuffer = hqNxAsmHelper(&HQnX_asm::hq3x_32, 3, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); + else if (mult == 4) + texbuffer.mBuffer = hqNxAsmHelper(&HQnX_asm::hq4x_32, 4, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); + else return; + } +#endif + else if (type == 4) + texbuffer.mBuffer = xbrzHelper(xbrz::scale, mult, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); + else if (type == 5) + texbuffer.mBuffer = xbrzHelper(xbrzOldScale, mult, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); + else if (type == 6) + texbuffer.mBuffer = normalNxHelper(&normalNx, mult, texbuffer.mBuffer, inWidth, inHeight, texbuffer.mWidth, texbuffer.mHeight); + else + return; + } + else + { + texbuffer.mWidth *= mult; + texbuffer.mHeight *= mult; + } + // Encode the scaling method in the content ID. + FContentIdBuilder contentId; + contentId.id = texbuffer.mContentId; + contentId.scaler = type; + contentId.scalefactor = mult; + texbuffer.mContentId = contentId.id; } diff --git a/src/textures/textures.h b/src/textures/textures.h index d25026634..778909be5 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -330,6 +330,7 @@ public: int isWarped() const { return bWarped; } int GetRotations() const { return Rotations; } void SetRotations(int rot) { Rotations = int16_t(rot); } + bool isSprite() const { return UseType == ETextureType::Sprite || UseType == ETextureType::SkinSprite || UseType == ETextureType::Decal; } const FString &GetName() const { return Name; } bool allowNoDecals() const { return bNoDecals; }