- enable the texture scalers in software mode.

Currently only implemented for 8 bit in the classic renderer.
This commit is contained in:
Christoph Oelckers 2018-12-15 00:38:27 +01:00
parent 656dbc9647
commit 4d8e8e7741
5 changed files with 126 additions and 87 deletions

View file

@ -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)
{

View file

@ -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();
}

View file

@ -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<class T> 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()
{

View file

@ -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;
}

View file

@ -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; }