mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-11 15:22:16 +00:00
- enable the texture scalers in software mode.
Currently only implemented for 8 bit in the classic renderer.
This commit is contained in:
parent
656dbc9647
commit
4d8e8e7741
5 changed files with 126 additions and 87 deletions
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -21,6 +21,9 @@ 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);
|
||||
|
@ -28,12 +31,7 @@ protected:
|
|||
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()
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
|
|
Loading…
Reference in a new issue