- added a few more texture formats to FHardwareTexture.

For brightmaps we do not need full RGBA8 data with mipmaps - RGBA2 without mipmaps is fully sufficient here and will save a lot of video memory.
This commit is contained in:
Christoph Oelckers 2019-10-19 23:14:36 +02:00
parent 7d2f61db2e
commit bb4a19cf3a
9 changed files with 34 additions and 64 deletions

View file

@ -398,7 +398,7 @@ int32_t animvpx_render_frame(animvpx_codec_ctx *codec, double animvpx_aspect)
if (!texuploaded) if (!texuploaded)
{ {
texture->CreateTexture(codec->width, codec->height, false, false); texture->CreateTexture(codec->width, codec->height, FHardwareTexture::TrueColor, false);
texuploaded = 1; texuploaded = 1;
} }
texture->LoadTexture(codec->pic); texture->LoadTexture(codec->pic);

View file

@ -27,7 +27,7 @@ bool glsurface_initialize(vec2_t bufferResolution)
buffer.Resize(bufferRes.x * bufferRes.y); buffer.Resize(bufferRes.x * bufferRes.y);
bufferTexture = GLInterface.NewTexture(); bufferTexture = GLInterface.NewTexture();
bufferTexture->CreateTexture(bufferRes.x, bufferRes.y, true, false); bufferTexture->CreateTexture(bufferRes.x, bufferRes.y, FHardwareTexture::Indexed, false);
glsurface_setPalette(curpalettefaded); glsurface_setPalette(curpalettefaded);
GLInterface.SetSurfaceShader(); GLInterface.SetSurfaceShader();
@ -52,7 +52,7 @@ void glsurface_setPalette(void* pPalette)
if (!paletteTexture) if (!paletteTexture)
{ {
paletteTexture = GLInterface.NewTexture(); paletteTexture = GLInterface.NewTexture();
paletteTexture->CreateTexture(256, 1, false, false); paletteTexture->CreateTexture(256, 1, FHardwareTexture::TrueColor, false);
} }
paletteTexture->LoadTexture(palette); paletteTexture->LoadTexture(palette);
GLInterface.BindTexture(1, paletteTexture, SamplerNoFilterClampXY); GLInterface.BindTexture(1, paletteTexture, SamplerNoFilterClampXY);

View file

@ -5230,7 +5230,7 @@ static int32_t gen_font_glyph_tex(void)
} }
} }
polymosttext->CreateTexture(256, 128, false, false); polymosttext->CreateTexture(256, 128, FHardwareTexture::TrueColor, false);
polymosttext->LoadTexture((uint8_t*)tbuf); polymosttext->LoadTexture((uint8_t*)tbuf);
polymosttext->SetSampler(SamplerNoFilterClampXY); polymosttext->SetSampler(SamplerNoFilterClampXY);
Xfree(tbuf); Xfree(tbuf);

View file

@ -51,7 +51,7 @@ FHardwareTexture* GLInstance::CreateIndexedTexture(FTexture* tex)
} }
auto glpic = GLInterface.NewTexture(); auto glpic = GLInterface.NewTexture();
glpic->CreateTexture(siz.x, siz.y, true, false); glpic->CreateTexture(siz.x, siz.y, FHardwareTexture::Indexed, false);
TArray<uint8_t> flipped(siz.x * siz.y, true); TArray<uint8_t> flipped(siz.x * siz.y, true);
FlipNonSquareBlock(flipped.Data(), p, siz.y, siz.x, siz.y); FlipNonSquareBlock(flipped.Data(), p, siz.y, siz.x, siz.y);
@ -65,7 +65,7 @@ FHardwareTexture* GLInstance::CreateIndexedTexture(FTexture* tex)
// //
//=========================================================================== //===========================================================================
FHardwareTexture* GLInstance::CreateTrueColorTexture(FTexture* tex, int palid, bool checkfulltransparency) FHardwareTexture* GLInstance::CreateTrueColorTexture(FTexture* tex, int palid, bool checkfulltransparency, bool rgb8bit)
{ {
auto siz = tex->GetSize(); auto siz = tex->GetSize();
bool npoty = false; bool npoty = false;
@ -89,7 +89,10 @@ FHardwareTexture* GLInstance::CreateTrueColorTexture(FTexture* tex, int palid, b
} }
auto glpic = GLInterface.NewTexture(); auto glpic = GLInterface.NewTexture();
glpic->CreateTexture(texbuffer.mWidth, texbuffer.mHeight, false, true); if (!rgb8bit)
glpic->CreateTexture(texbuffer.mWidth, texbuffer.mHeight, FHardwareTexture::TrueColor, true);
else
glpic->CreateTexture(texbuffer.mWidth, texbuffer.mHeight, FHardwareTexture::Brightmap, false); // Use a more memory friendly format for simple brightmaps.
glpic->LoadTexture(texbuffer.mBuffer); glpic->LoadTexture(texbuffer.mBuffer);
return glpic; return glpic;
} }
@ -110,7 +113,7 @@ FHardwareTexture* GLInstance::LoadTexture(FTexture* tex, int textype, int palid)
if (textype == TT_INDEXED) if (textype == TT_INDEXED)
hwtex = CreateIndexedTexture(tex); hwtex = CreateIndexedTexture(tex);
else else
hwtex = CreateTrueColorTexture(tex, textype == TT_HICREPLACE? -1 : palid, textype == TT_BRIGHTMAP); hwtex = CreateTrueColorTexture(tex, textype == TT_HICREPLACE? -1 : palid, textype == TT_BRIGHTMAP, textype == TT_BRIGHTMAP);
tex->SetHardwareTexture(palid, hwtex); tex->SetHardwareTexture(palid, hwtex);
return hwtex; return hwtex;

View file

@ -69,7 +69,7 @@ FHardwareTexture *gloadtex(const int32_t *picbuf, int32_t xsiz, int32_t ysiz, in
} }
auto tex = GLInterface.NewTexture(); auto tex = GLInterface.NewTexture();
tex->CreateTexture(xsiz, ysiz, false, false); tex->CreateTexture(xsiz, ysiz, FHardwareTexture::TrueColor, false);
tex->LoadTexture((uint8_t*)pic2); tex->LoadTexture((uint8_t*)pic2);
tex->SetSampler(SamplerNoFilterClampXY); tex->SetSampler(SamplerNoFilterClampXY);
Xfree(pic2); Xfree(pic2);

View file

@ -38,20 +38,21 @@
// //
//=========================================================================== //===========================================================================
unsigned int FHardwareTexture::CreateTexture(int w, int h, bool eightbit, bool mipmapped) unsigned int FHardwareTexture::CreateTexture(int w, int h, int type, bool mipmapped)
{ {
static int gltypes[] = { GL_R8, GL_RGBA8, GL_RGB5_A1, GL_RGBA2 };
glTexID = GLInterface.GetTextureID(); glTexID = GLInterface.GetTextureID();
glActiveTexture(GL_TEXTURE15); glActiveTexture(GL_TEXTURE15);
glBindTexture(GL_TEXTURE_2D, glTexID); glBindTexture(GL_TEXTURE_2D, glTexID);
int size = std::max(w, h); int size = std::max(w, h);
int bits = 0; int bits = 0;
while (size) bits++, size >>= 1; while (size) bits++, size >>= 1;
glTextureBytes = eightbit? 1 : 4; internalType = type;
if (eightbit) mipmapped = false; if (type == Indexed) mipmapped = false;
mWidth = w; mWidth = w;
mHeight = h; mHeight = h;
glTexStorage2D(GL_TEXTURE_2D, mipmapped? bits : 1, eightbit? GL_R8 : GL_RGBA8, w, h); glTexStorage2D(GL_TEXTURE_2D, mipmapped? bits : 1, gltypes[type], w, h);
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
this->mipmapped = mipmapped; this->mipmapped = mipmapped;
@ -85,20 +86,19 @@ unsigned int FHardwareTexture::LoadTexturePart(const unsigned char* buffer, int
{ {
if (glTexID == 0) return 0; if (glTexID == 0) return 0;
int dstformat = glTextureBytes == 1 ? GL_R8 : GL_RGBA8;// TexFormat[gl_texture_format]; int srcformat = internalType == Indexed ? GL_RED : GL_BGRA;// TexFormat[gl_texture_format];
int srcformat = glTextureBytes == 1 ? GL_RED : GL_BGRA;// TexFormat[gl_texture_format];
glActiveTexture(GL_TEXTURE15); glActiveTexture(GL_TEXTURE15);
glBindTexture(GL_TEXTURE_2D, glTexID); glBindTexture(GL_TEXTURE_2D, glTexID);
if (glTextureBytes < 4) glPixelStorei(GL_UNPACK_ALIGNMENT, 1); if (internalType == Indexed) glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, srcformat, GL_UNSIGNED_BYTE, buffer); glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, srcformat, GL_UNSIGNED_BYTE, buffer);
if (mipmapped) glGenerateMipmap(GL_TEXTURE_2D); if (mipmapped) glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
if (glTextureBytes < 4) glPixelStorei(GL_UNPACK_ALIGNMENT, 4); if (internalType == Indexed) glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
return glTexID; return glTexID;
} }

View file

@ -10,12 +10,19 @@ class FTexture;
class FHardwareTexture //: public IHardwareTexture class FHardwareTexture //: public IHardwareTexture
{ {
public: public:
enum
{
Indexed,
TrueColor,
HighColor, // 16 bit - Can be used to save space in memory constrained scenarios at the cost of visual accuracy.
Brightmap, // This can be stored as RGBA2 to save space, it also doesn't really need a mipmap.
};
private: private:
int mSampler = 0; int mSampler = 0;
unsigned int glTexID = 0; unsigned int glTexID = 0;
int glTextureBytes = 4; int internalType = TrueColor;
bool mipmapped = true; bool mipmapped = true;
int mWidth = 0, mHeight = 0; int mWidth = 0, mHeight = 0;
int colorId = 0; int colorId = 0;
@ -26,56 +33,18 @@ public:
//bool BindOrCreate(FTexture *tex, int texunit, int clampmode, int translation, int flags); //bool BindOrCreate(FTexture *tex, int texunit, int clampmode, int translation, int flags);
unsigned int CreateTexture(int w, int h, bool eightbit, bool mipmapped); unsigned int CreateTexture(int w, int h, bool type, bool mipmapped) = delete;
unsigned int CreateTexture(int w, int h, int type, bool mipmapped);
unsigned int LoadTexture(const unsigned char * buffer); unsigned int LoadTexture(const unsigned char * buffer);
unsigned int LoadTexturePart(const unsigned char* buffer, int x, int y, int w, int h); unsigned int LoadTexturePart(const unsigned char* buffer, int x, int y, int w, int h);
unsigned int LoadTexture(FBitmap &bmp); unsigned int LoadTexture(FBitmap &bmp);
unsigned int GetTextureHandle(); unsigned int GetTextureHandle();
int GetSampler() { return mSampler; } int GetSampler() { return mSampler; }
void SetSampler(int sampler) { mSampler = sampler; } void SetSampler(int sampler) { mSampler = sampler; }
bool isIndexed() const { return glTextureBytes == 1; } bool isIndexed() const { return internalType == Indexed; }
friend class FGameTexture; friend class FGameTexture;
}; };
// This class identifies a single source image to the game.
// Since hightile palette variations are identified by file name, they will create separate game textures.
class FGameTexture
{
int Width, Height;
bool isHightile;
// Source image for this texture.
FTexture* sourceData = nullptr;
// indexed or the sole image for hightiles.
FHardwareTexture* hwBase = nullptr;
// If the number was large a TMap would be better -
// but in most cases the maximum number of palettes for a single tile is less than 10 where a linear search is much faster than a TMap.
TArray<FHardwareTexture*> hwTextures;
public:
FGameTexture(bool hightile, int width, int height);
virtual ~FGameTexture();
// For dynamic subtypes.
virtual void SizeChanged(int width, int height);
static constexpr int MakeId(int palette, int palswap)
{
return palette + 256 * palswap;
}
FHardwareTexture* GetBaseTexture();
FHardwareTexture* CreateHardwareTexture(int palette, int palswap);
FHardwareTexture* GetHardwareTexture(int palette, int palswap)
{
if (isHightile) return GetBaseTexture();
auto id = MakeId(palette, palswap);
auto found = hwTextures.FindEx([=](FHardwareTexture* tex)
{
return tex->colorId == id;
});
if (!found) return CreateHardwareTexture(palette, palswap);
}
};
#endif #endif

View file

@ -195,7 +195,7 @@ void PaletteManager::BindPalette(int index)
if (palettes[uindex].paltexture == nullptr) if (palettes[uindex].paltexture == nullptr)
{ {
auto p = GLInterface.NewTexture(); auto p = GLInterface.NewTexture();
p->CreateTexture(256, 1, false, false); p->CreateTexture(256, 1, FHardwareTexture::TrueColor, false);
p->LoadTexture((uint8_t*)palettes[uindex].colors); p->LoadTexture((uint8_t*)palettes[uindex].colors);
p->SetSampler(SamplerNoFilterClampXY); p->SetSampler(SamplerNoFilterClampXY);
palettes[uindex].paltexture = p; palettes[uindex].paltexture = p;
@ -237,7 +237,7 @@ void PaletteManager::BindPalswap(int index)
if (ps.swaptexture == nullptr) if (ps.swaptexture == nullptr)
{ {
auto p = GLInterface.NewTexture(); auto p = GLInterface.NewTexture();
p->CreateTexture(256, numshades, true, false); p->CreateTexture(256, numshades, FHardwareTexture::Indexed, false);
p->LoadTexture((uint8_t*)ps.lookup); p->LoadTexture((uint8_t*)ps.lookup);
p->SetSampler(SamplerNoFilterClampXY); p->SetSampler(SamplerNoFilterClampXY);
ps.swaptexture = p; ps.swaptexture = p;

View file

@ -245,9 +245,7 @@ public:
int GetTextureID(); int GetTextureID();
FHardwareTexture* NewTexture(); FHardwareTexture* NewTexture();
FGameTexture* NewTexture(const char *name, bool hightile);
void BindTexture(int texunit, FHardwareTexture *texid, int sampler = NoSampler); void BindTexture(int texunit, FHardwareTexture *texid, int sampler = NoSampler);
void BindTexture(int texunit, FGameTexture* texid, int sampler = NoSampler);
void UnbindTexture(int texunit); void UnbindTexture(int texunit);
void UnbindAllTextures(); void UnbindAllTextures();
void EnableBlend(bool on); void EnableBlend(bool on);
@ -395,7 +393,7 @@ public:
} }
FHardwareTexture* CreateIndexedTexture(FTexture* tex); FHardwareTexture* CreateIndexedTexture(FTexture* tex);
FHardwareTexture* CreateTrueColorTexture(FTexture* tex, int palid, bool checkfulltransparency = false); FHardwareTexture* CreateTrueColorTexture(FTexture* tex, int palid, bool checkfulltransparency = false, bool rgb8bit = false);
FHardwareTexture *LoadTexture(FTexture* tex, int texturetype, int palid); FHardwareTexture *LoadTexture(FTexture* tex, int texturetype, int palid);
bool SetTextureInternal(int globalpicnum, FTexture* tex, int palette, int method, int sampleroverride, float xpanning, float ypanning, FTexture *det, float detscale, FTexture *glow); bool SetTextureInternal(int globalpicnum, FTexture* tex, int palette, int method, int sampleroverride, float xpanning, float ypanning, FTexture *det, float detscale, FTexture *glow);