- allocate the sprite positioning info on demand only.

For most textures this is never needed and it can easily be put in the memory arena being used for image sources.
This commit is contained in:
Christoph Oelckers 2020-04-16 18:46:31 +02:00
parent c5e81c54a2
commit 095a5e2c0a
5 changed files with 71 additions and 70 deletions

View file

@ -41,7 +41,7 @@
#include "cmdlib.h"
#include "palettecontainer.h"
FMemArena FImageSource::ImageArena(32768);
FMemArena ImageArena(32768);
TArray<FImageSource *>FImageSource::ImageForLump;
int FImageSource::NextID;
static PrecacheInfo precacheInfo;

View file

@ -7,6 +7,7 @@
class FImageSource;
using PrecacheInfo = TMap<int, std::pair<int, int>>;
extern FMemArena ImageArena;
// Doom patch format header
struct patch_t
@ -38,7 +39,6 @@ class FImageSource
friend class FBrightmapTexture;
protected:
static FMemArena ImageArena;
static TArray<FImageSource *>ImageForLump;
static int NextID;

View file

@ -737,29 +737,6 @@ TArray<uint8_t> FTexture::Get8BitPixels(bool alphatex)
return Pixels;
}
//===========================================================================
//
// Sets up the sprite positioning data for this texture
//
//===========================================================================
void FTexture::SetupSpriteData()
{
spi.mSpriteU[0] = spi.mSpriteV[0] = 0.f;
spi.mSpriteU[1] = spi.mSpriteV[1] = 1.f;
spi.spriteWidth = GetTexelWidth();
spi.spriteHeight = GetTexelHeight();
if (ShouldExpandSprite())
{
if (mTrimResult == -1) mTrimResult = !!TrimBorders(spi.trim); // get the trim size before adding the empty frame
spi.spriteWidth += 2;
spi.spriteHeight += 2;
}
else mTrimResult = 0;
SetSpriteRect();
}
//===========================================================================
//
// Checks if a sprite may be expanded with an empty frame
@ -875,54 +852,90 @@ outl:
}
//===========================================================================
//
// Sets up the sprite positioning data for this texture
//
// Set the sprite rectangle
//===========================================================================
void FTexture::SetupSpriteData()
{
// Since this is only needed for real sprites it gets allocated on demand.
// It also allocates from the image memory arena because it has the same lifetime and to reduce maintenance.
if (spi == nullptr) spi = (SpritePositioningInfo*)ImageArena.Alloc(2 * sizeof(SpritePositioningInfo));
for (int i = 0; i < 2; i++)
{
auto& spi = this->spi[i];
spi.mSpriteU[0] = spi.mSpriteV[0] = 0.f;
spi.mSpriteU[1] = spi.mSpriteV[1] = 1.f;
spi.spriteWidth = GetTexelWidth();
spi.spriteHeight = GetTexelHeight();
if (i == 1 && ShouldExpandSprite())
{
spi.mTrimResult = TrimBorders(spi.trim); // get the trim size before adding the empty frame
spi.spriteWidth += 2;
spi.spriteHeight += 2;
}
}
SetSpriteRect();
}
//===========================================================================
//
// Set the sprite rectangle. This is separate because it may be called by a CVAR, too.
//
//===========================================================================
void FTexture::SetSpriteRect()
{
if (!spi) return;
auto leftOffset = GetLeftOffsetHW();
auto topOffset = GetTopOffsetHW();
float fxScale = (float)Scale.X;
float fyScale = (float)Scale.Y;
// mSpriteRect is for positioning the sprite in the scene.
spi.mSpriteRect.left = -leftOffset / fxScale;
spi.mSpriteRect.top = -topOffset / fyScale;
spi.mSpriteRect.width = spi.spriteWidth / fxScale;
spi.mSpriteRect.height = spi.spriteHeight / fyScale;
if (bExpandSprite)
for (int i = 0; i < 2; i++)
{
// a little adjustment to make sprites look better with texture filtering:
// create a 1 pixel wide empty frame around them.
auto& spi = this->spi[i];
int oldwidth = spi.spriteWidth - 2;
int oldheight = spi.spriteHeight - 2;
// mSpriteRect is for positioning the sprite in the scene.
spi.mSpriteRect.left = -leftOffset / fxScale;
spi.mSpriteRect.top = -topOffset / fyScale;
spi.mSpriteRect.width = spi.spriteWidth / fxScale;
spi.mSpriteRect.height = spi.spriteHeight / fyScale;
leftOffset += 1;
topOffset += 1;
// Reposition the sprite with the frame considered
spi.mSpriteRect.left = -(float)leftOffset / fxScale;
spi.mSpriteRect.top = -(float)topOffset / fyScale;
spi.mSpriteRect.width = (float)spi.spriteWidth / fxScale;
spi.mSpriteRect.height = (float)spi.spriteHeight / fyScale;
if (mTrimResult > 0)
if (i == 1 && ShouldExpandSprite())
{
spi.mSpriteRect.left += (float)spi.trim[0] / fxScale;
spi.mSpriteRect.top += (float)spi.trim[1] / fyScale;
// a little adjustment to make sprites look better with texture filtering:
// create a 1 pixel wide empty frame around them.
spi.mSpriteRect.width -= float(oldwidth - spi.trim[2]) / fxScale;
spi.mSpriteRect.height -= float(oldheight - spi.trim[3]) / fyScale;
int oldwidth = spi.spriteWidth - 2;
int oldheight = spi.spriteHeight - 2;
spi.mSpriteU[0] = (float)spi.trim[0] / (float)spi.spriteWidth;
spi.mSpriteV[0] = (float)spi.trim[1] / (float)spi.spriteHeight;
spi.mSpriteU[1] -= float(oldwidth - spi.trim[0] - spi.trim[2]) / (float)spi.spriteWidth;
spi.mSpriteV[1] -= float(oldheight - spi.trim[1] - spi.trim[3]) / (float)spi.spriteHeight;
leftOffset += 1;
topOffset += 1;
// Reposition the sprite with the frame considered
spi.mSpriteRect.left = -(float)leftOffset / fxScale;
spi.mSpriteRect.top = -(float)topOffset / fyScale;
spi.mSpriteRect.width = (float)spi.spriteWidth / fxScale;
spi.mSpriteRect.height = (float)spi.spriteHeight / fyScale;
if (spi.mTrimResult > 0)
{
spi.mSpriteRect.left += (float)spi.trim[0] / fxScale;
spi.mSpriteRect.top += (float)spi.trim[1] / fyScale;
spi.mSpriteRect.width -= float(oldwidth - spi.trim[2]) / fxScale;
spi.mSpriteRect.height -= float(oldheight - spi.trim[3]) / fyScale;
spi.mSpriteU[0] = (float)spi.trim[0] / (float)spi.spriteWidth;
spi.mSpriteV[0] = (float)spi.trim[1] / (float)spi.spriteHeight;
spi.mSpriteU[1] -= float(oldwidth - spi.trim[0] - spi.trim[2]) / (float)spi.spriteWidth;
spi.mSpriteV[1] -= float(oldheight - spi.trim[1] - spi.trim[3]) / (float)spi.spriteHeight;
}
}
}
}

View file

@ -1488,9 +1488,3 @@ FTextureID FTextureID::operator +(int offset) throw()
if (texnum + offset >= TexMan.NumTextures()) return FTextureID(-1);
return FTextureID(texnum + offset);
}
CCMD(texinfo)
{
Printf("Sizeof texture = %d\n", sizeof(FTexture));
}

View file

@ -229,6 +229,7 @@ struct SpritePositioningInfo
int spriteWidth, spriteHeight;
float mSpriteU[2], mSpriteV[2];
FloatRect mSpriteRect;
uint8_t mTrimResult;
float GetSpriteUL() const { return mSpriteU[0]; }
float GetSpriteVT() const { return mSpriteV[0]; }
@ -255,8 +256,7 @@ class FTexture
public:
SpritePositioningInfo spi;
int8_t mTrimResult = -1;
SpritePositioningInfo *spi = nullptr;
IHardwareTexture* GetHardwareTexture(int translation, bool expanded);
static FTexture *CreateTexture(const char *name, int lumpnum, ETextureType usetype);
@ -375,12 +375,6 @@ public:
protected:
ISoftwareTexture *SoftwareTexture = nullptr;
// None of the following pointers are owned by this texture, they are all controlled by the texture manager.
// Offset-less version for COMPATF_MASKEDMIDTEX
FGameTexture *OffsetLess = nullptr;
// Front sky layer variant where color 0 is transparent
FGameTexture* FrontSkyLayer = nullptr;
public:
// Material layers
FTexture *Brightmap = nullptr;
@ -736,7 +730,7 @@ public:
void SetDisplaySize(float w, float h) { wrapped.SetSize((int)w, (int)h); }
void SetSpriteRect() { wrapped.SetSpriteRect(); }
const SpritePositioningInfo& GetSpritePositioning(int which) { /* todo: keep two sets of positioning infd*/ if (wrapped.mTrimResult == -1) wrapped.SetupSpriteData(); return wrapped.spi; }
const SpritePositioningInfo& GetSpritePositioning(int which) { if (wrapped.spi == nullptr) wrapped.SetupSpriteData(); return wrapped.spi[which]; }
int GetAreas(FloatRect** pAreas) const { return wrapped.GetAreas(pAreas); }
PalEntry GetSkyCapColor(bool bottom) { return wrapped.GetSkyCapColor(bottom); }