mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-11 15:22:16 +00:00
- implemented a proper texture composition cache.
This will mostly ensure that each patch used for composition is only loaded once and automatically unloaded once no longer needed. So far only for paletted rendering, but the same logic can be used for true color as well.
This commit is contained in:
parent
796c0fe931
commit
2e7bcf9e41
32 changed files with 367 additions and 60 deletions
|
@ -373,7 +373,14 @@ void OpenGLFrameBuffer::PrecacheMaterial(FMaterial *mat, int translation)
|
|||
FHardwareTexture::UnbindAll();
|
||||
}
|
||||
|
||||
FModelRenderer *OpenGLFrameBuffer::CreateModelRenderer(int mli)
|
||||
bool OpenGLFrameBuffer::CheckPrecacheMaterial(FMaterial *mat)
|
||||
{
|
||||
if (!mat->tex->GetImage()) return true;
|
||||
auto base = static_cast<FHardwareTexture*>(mat->GetLayer(0));
|
||||
return base->Exists(0);
|
||||
}
|
||||
|
||||
FModelRenderer *OpenGLFrameBuffer::CreateModelRenderer(int mli)
|
||||
{
|
||||
return new FGLModelRenderer(nullptr, gl_RenderState, mli);
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ public:
|
|||
void SetTextureFilterMode() override;
|
||||
IHardwareTexture *CreateHardwareTexture(FTexture *tex) override;
|
||||
void PrecacheMaterial(FMaterial *mat, int translation) override;
|
||||
bool CheckPrecacheMaterial(FMaterial *mat) override;
|
||||
FModelRenderer *CreateModelRenderer(int mli) override;
|
||||
void TextureFilterChanged() override;
|
||||
void BeginFrame() override;
|
||||
|
|
|
@ -467,4 +467,29 @@ bool FHardwareTexture::BindOrCreate(FTexture *tex, int texunit, int clampmode, i
|
|||
return true;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Binds a texture to the renderer
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
bool FHardwareTexture::Exists(int translation)
|
||||
{
|
||||
int usebright = false;
|
||||
|
||||
if (translation <= 0)
|
||||
{
|
||||
translation = -translation;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto remap = TranslationToTable(translation);
|
||||
translation = remap == nullptr ? 0 : remap->GetUniqueIndex();
|
||||
}
|
||||
|
||||
TranslatedTexture *pTex = GetTexID(translation);
|
||||
return (pTex->glTexID != 0);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -81,6 +81,7 @@ public:
|
|||
|
||||
unsigned int Bind(int texunit, int translation, bool needmipmap);
|
||||
bool BindOrCreate(FTexture *tex, int texunit, int clampmode, int translation, int flags);
|
||||
bool Exists(int translation);
|
||||
|
||||
void AllocateBuffer(int w, int h, int texelsize);
|
||||
uint8_t *MapBuffer();
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "r_data/models/models.h"
|
||||
#include "textures/skyboxtexture.h"
|
||||
#include "hwrenderer/textures/hw_material.h"
|
||||
#include "image.h"
|
||||
|
||||
|
||||
//==========================================================================
|
||||
|
@ -189,6 +190,31 @@ void hw_PrecacheTexture(uint8_t *texhitlist, TMap<PClassActor*, bool> &actorhitl
|
|||
|
||||
if (gl_precache)
|
||||
{
|
||||
FImageSource::BeginPrecaching();
|
||||
|
||||
// cache all used textures
|
||||
for (int i = cnt - 1; i >= 0; i--)
|
||||
{
|
||||
FTexture *tex = TexMan.ByIndex(i);
|
||||
if (tex != nullptr && tex->GetImage() != nullptr)
|
||||
{
|
||||
if (texhitlist[i] & (FTextureManager::HIT_Wall | FTextureManager::HIT_Flat | FTextureManager::HIT_Sky))
|
||||
{
|
||||
FMaterial * gltex = FMaterial::ValidateTexture(tex, false);
|
||||
if (gltex && !screen->CheckPrecacheMaterial(gltex))
|
||||
{
|
||||
FImageSource::RegisterForPrecache(tex->GetImage());
|
||||
}
|
||||
}
|
||||
|
||||
// Only register untranslated sprites. Translated ones are very unlikely to require data that can be reused.
|
||||
if (spritehitlist[i] != nullptr && (*spritehitlist[i]).CheckKey(0))
|
||||
{
|
||||
FImageSource::RegisterForPrecache(tex->GetImage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// cache all used textures
|
||||
for (int i = cnt - 1; i >= 0; i--)
|
||||
{
|
||||
|
@ -203,6 +229,9 @@ void hw_PrecacheTexture(uint8_t *texhitlist, TMap<PClassActor*, bool> &actorhitl
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
FImageSource::EndPrecaching();
|
||||
|
||||
// cache all used models
|
||||
FModelRenderer *renderer = screen->CreateModelRenderer(-1);
|
||||
for (unsigned i = 0; i < Models.Size(); i++)
|
||||
|
|
|
@ -53,7 +53,7 @@ public:
|
|||
FVoxelTexture(FVoxel *voxel);
|
||||
|
||||
int CopyPixels(FBitmap *bmp, int conversion) override;
|
||||
TArray<uint8_t> GetPalettedPixels(int conversion) override;
|
||||
TArray<uint8_t> CreatePalettedPixels(int conversion) override;
|
||||
|
||||
protected:
|
||||
FVoxel *SourceVox;
|
||||
|
@ -79,7 +79,7 @@ FVoxelTexture::FVoxelTexture(FVoxel *vox)
|
|||
//
|
||||
//===========================================================================
|
||||
|
||||
TArray<uint8_t> FVoxelTexture::GetPalettedPixels(int conversion)
|
||||
TArray<uint8_t> FVoxelTexture::CreatePalettedPixels(int conversion)
|
||||
{
|
||||
// GetPixels gets called when a translated palette is used so we still need to implement it here.
|
||||
TArray<uint8_t> Pixels(256, true);
|
||||
|
|
|
@ -818,6 +818,7 @@ namespace swrenderer
|
|||
|
||||
FTexture *tex = TexMan.GetPalettedTexture(sidedef->GetTexture(side_t::top), true);
|
||||
mTopPart.Texture = tex && tex->isValid() ? tex->GetSoftwareTexture() : nullptr;
|
||||
if (mTopPart.Texture == nullptr) return;
|
||||
|
||||
mTopPart.TextureOffsetU = FLOAT2FIXED(sidedef->GetTextureXOffset(side_t::top));
|
||||
double rowoffset = sidedef->GetTextureYOffset(side_t::top);
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
#include "polyrenderer/poly_renderer.h"
|
||||
#include "p_setup.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "image.h"
|
||||
|
||||
// [BB] Use ZDoom's freelook limit for the sotfware renderer.
|
||||
// Note: ZDoom's limit is chosen such that the sky is rendered properly.
|
||||
|
@ -80,6 +81,25 @@ FRenderer *CreateSWRenderer()
|
|||
return new FSoftwareRenderer;
|
||||
}
|
||||
|
||||
void FSoftwareRenderer::PreparePrecache(FTexture *ttex, int cache)
|
||||
{
|
||||
bool isbgra = V_IsTrueColor();
|
||||
|
||||
if (ttex != NULL && ttex->isValid())
|
||||
{
|
||||
FSoftwareTexture *tex = ttex->GetSoftwareTexture();
|
||||
|
||||
if (tex->CheckPixels())
|
||||
{
|
||||
if (cache == 0) tex->Unload();
|
||||
}
|
||||
else if (cache != 0)
|
||||
{
|
||||
FImageSource::RegisterForPrecache(ttex->GetImage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FSoftwareRenderer::PrecacheTexture(FTexture *ttex, int cache)
|
||||
{
|
||||
bool isbgra = V_IsTrueColor();
|
||||
|
@ -102,10 +122,6 @@ void FSoftwareRenderer::PrecacheTexture(FTexture *ttex, int cache)
|
|||
else
|
||||
tex->GetPixels (DefaultRenderStyle());
|
||||
}
|
||||
else
|
||||
{
|
||||
tex->Unload ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -152,10 +168,18 @@ void FSoftwareRenderer::Precache(uint8_t *texhitlist, TMap<PClassActor*, bool> &
|
|||
delete[] spritelist;
|
||||
|
||||
int cnt = TexMan.NumTextures();
|
||||
|
||||
FImageSource::BeginPrecaching();
|
||||
for (int i = cnt - 1; i >= 0; i--)
|
||||
{
|
||||
PreparePrecache(TexMan.ByIndex(i), texhitlist[i]);
|
||||
}
|
||||
|
||||
for (int i = cnt - 1; i >= 0; i--)
|
||||
{
|
||||
PrecacheTexture(TexMan.ByIndex(i), texhitlist[i]);
|
||||
}
|
||||
FImageSource::EndPrecaching();
|
||||
}
|
||||
|
||||
void FSoftwareRenderer::RenderView(player_t *player, DCanvas *target, void *videobuffer)
|
||||
|
|
|
@ -27,6 +27,7 @@ struct FSoftwareRenderer : public FRenderer
|
|||
void Init() override;
|
||||
|
||||
private:
|
||||
void PreparePrecache(FTexture *tex, int cache);
|
||||
void PrecacheTexture(FTexture *tex, int cache);
|
||||
|
||||
swrenderer::RenderScene mScene;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
#include "textures/textures.h"
|
||||
|
||||
#include "v_video.h"
|
||||
|
||||
struct FSoftwareTextureSpan
|
||||
{
|
||||
|
@ -130,6 +130,12 @@ public:
|
|||
return GetPixels(alpha);
|
||||
}
|
||||
|
||||
// Checks if the pixel data is loaded.
|
||||
bool CheckPixels() const
|
||||
{
|
||||
return V_IsTrueColor() ? PixelsBgra.Size() > 0 : Pixels.Size() > 0;
|
||||
}
|
||||
|
||||
const uint8_t *GetColumn(FRenderStyle style, unsigned int column, const FSoftwareTextureSpan **spans_out)
|
||||
{
|
||||
bool alpha = !!(style.Flags & STYLEF_RedIsAlpha);
|
||||
|
|
14
src/tarray.h
14
src/tarray.h
|
@ -272,6 +272,18 @@ public:
|
|||
return i;
|
||||
}
|
||||
|
||||
template<class Func> const
|
||||
unsigned int FindEx(Func compare) const
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; i < Count; ++i)
|
||||
{
|
||||
if (compare(Array[i]))
|
||||
break;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
unsigned int Push (const T &item)
|
||||
{
|
||||
Grow (1);
|
||||
|
@ -1019,7 +1031,7 @@ protected:
|
|||
if (!nold[i].IsNil())
|
||||
{
|
||||
Node *n = NewKey(nold[i].Pair.Key);
|
||||
::new(&n->Pair.Value) VT(nold[i].Pair.Value);
|
||||
::new(&n->Pair.Value) VT(std::move(nold[i].Pair.Value));
|
||||
nold[i].~Node();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ class FAutomapTexture : public FImageSource
|
|||
{
|
||||
public:
|
||||
FAutomapTexture(int lumpnum);
|
||||
TArray<uint8_t> GetPalettedPixels(int conversion) override;
|
||||
TArray<uint8_t> CreatePalettedPixels(int conversion) override;
|
||||
};
|
||||
|
||||
|
||||
|
@ -91,7 +91,7 @@ FAutomapTexture::FAutomapTexture (int lumpnum)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
TArray<uint8_t> FAutomapTexture::GetPalettedPixels(int conversion)
|
||||
TArray<uint8_t> FAutomapTexture::CreatePalettedPixels(int conversion)
|
||||
{
|
||||
int x, y;
|
||||
FMemLump data = Wads.ReadLump (SourceLump);
|
||||
|
|
|
@ -57,7 +57,7 @@ class FBuildTexture : public FImageSource
|
|||
{
|
||||
public:
|
||||
FBuildTexture (const FString &pathprefix, int tilenum, const uint8_t *pixels, int translation, int width, int height, int left, int top);
|
||||
TArray<uint8_t> GetPalettedPixels(int conversion) override;
|
||||
TArray<uint8_t> CreatePalettedPixels(int conversion) override;
|
||||
int CopyPixels(FBitmap *bmp, int conversion) override;
|
||||
|
||||
protected:
|
||||
|
@ -81,7 +81,7 @@ FBuildTexture::FBuildTexture(const FString &pathprefix, int tilenum, const uint8
|
|||
TopOffset = top;
|
||||
}
|
||||
|
||||
TArray<uint8_t> FBuildTexture::GetPalettedPixels(int conversion)
|
||||
TArray<uint8_t> FBuildTexture::CreatePalettedPixels(int conversion)
|
||||
{
|
||||
TArray<uint8_t> Pixels(Width * Height, true);
|
||||
FRemapTable *Remap = translationtables[TRANSLATION_Standard][Translation];
|
||||
|
|
|
@ -164,7 +164,7 @@ class FDDSTexture : public FImageSource
|
|||
public:
|
||||
FDDSTexture (FileReader &lump, int lumpnum, void *surfdesc);
|
||||
|
||||
TArray<uint8_t> GetPalettedPixels(int conversion) override;
|
||||
TArray<uint8_t> CreatePalettedPixels(int conversion) override;
|
||||
|
||||
protected:
|
||||
uint32_t Format;
|
||||
|
@ -372,7 +372,7 @@ void FDDSTexture::CalcBitShift (uint32_t mask, uint8_t *lshiftp, uint8_t *rshift
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
TArray<uint8_t> FDDSTexture::GetPalettedPixels(int conversion)
|
||||
TArray<uint8_t> FDDSTexture::CreatePalettedPixels(int conversion)
|
||||
{
|
||||
auto lump = Wads.OpenLumpReader (SourceLump);
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ class FEmptyTexture : public FImageSource
|
|||
{
|
||||
public:
|
||||
FEmptyTexture (int lumpnum);
|
||||
TArray<uint8_t> GetPalettedPixels(int conversion) override;
|
||||
TArray<uint8_t> CreatePalettedPixels(int conversion) override;
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
|
@ -91,7 +91,7 @@ FEmptyTexture::FEmptyTexture (int lumpnum)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
TArray<uint8_t> FEmptyTexture::GetPalettedPixels(int conversion)
|
||||
TArray<uint8_t> FEmptyTexture::CreatePalettedPixels(int conversion)
|
||||
{
|
||||
TArray<uint8_t> Pixel(1, true);
|
||||
Pixel[0] = 0;
|
||||
|
|
|
@ -50,7 +50,7 @@ class FFlatTexture : public FImageSource
|
|||
{
|
||||
public:
|
||||
FFlatTexture (int lumpnum);
|
||||
TArray<uint8_t> GetPalettedPixels(int conversion) override;
|
||||
TArray<uint8_t> CreatePalettedPixels(int conversion) override;
|
||||
};
|
||||
|
||||
|
||||
|
@ -104,7 +104,7 @@ FFlatTexture::FFlatTexture (int lumpnum)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
TArray<uint8_t> FFlatTexture::GetPalettedPixels(int conversion)
|
||||
TArray<uint8_t> FFlatTexture::CreatePalettedPixels(int conversion)
|
||||
{
|
||||
auto lump = Wads.OpenLumpReader (SourceLump);
|
||||
TArray<uint8_t> Pixels(Width*Height, true);
|
||||
|
|
|
@ -68,12 +68,12 @@ FFontChar1::FFontChar1 (FImageSource *sourcelump)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
TArray<uint8_t> FFontChar1::GetPalettedPixels (int)
|
||||
TArray<uint8_t> FFontChar1::CreatePalettedPixels (int)
|
||||
{
|
||||
// Make the texture as normal, then remap it so that all the colors
|
||||
// are at the low end of the palette
|
||||
// Why? It only creates unnecessary work!
|
||||
auto Pixels = BaseTexture->GetPalettedPixels(normal);
|
||||
auto Pixels = BaseTexture->CreatePalettedPixels(normal);
|
||||
|
||||
if (SourceRemap)
|
||||
{
|
||||
|
@ -132,7 +132,7 @@ void FFontChar2::SetSourceRemap(const uint8_t *sourceremap)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
TArray<uint8_t> FFontChar2::GetPalettedPixels(int)
|
||||
TArray<uint8_t> FFontChar2::CreatePalettedPixels(int)
|
||||
{
|
||||
auto lump = Wads.OpenLumpReader (SourceLump);
|
||||
int destSize = Width * Height;
|
||||
|
|
|
@ -5,7 +5,7 @@ class FFontChar1 : public FImageSource
|
|||
{
|
||||
public:
|
||||
FFontChar1 (FImageSource *sourcelump);
|
||||
TArray<uint8_t> GetPalettedPixels(int conversion) override;
|
||||
TArray<uint8_t> CreatePalettedPixels(int conversion) override;
|
||||
void SetSourceRemap(const uint8_t *sourceremap);
|
||||
|
||||
protected:
|
||||
|
@ -20,7 +20,7 @@ class FFontChar2 : public FImageSource
|
|||
public:
|
||||
FFontChar2 (int sourcelump, int sourcepos, int width, int height, int leftofs=0, int topofs=0);
|
||||
|
||||
TArray<uint8_t> GetPalettedPixels(int conversion) override;
|
||||
TArray<uint8_t> CreatePalettedPixels(int conversion) override;
|
||||
void SetSourceRemap(const uint8_t *sourceremap);
|
||||
|
||||
protected:
|
||||
|
|
|
@ -68,7 +68,7 @@ class FIMGZTexture : public FImageSource
|
|||
|
||||
public:
|
||||
FIMGZTexture (int lumpnum, uint16_t w, uint16_t h, int16_t l, int16_t t, bool isalpha);
|
||||
TArray<uint8_t> GetPalettedPixels(int conversion) override;
|
||||
TArray<uint8_t> CreatePalettedPixels(int conversion) override;
|
||||
int CopyPixels(FBitmap *bmp, int conversion) override;
|
||||
};
|
||||
|
||||
|
@ -120,7 +120,7 @@ FIMGZTexture::FIMGZTexture (int lumpnum, uint16_t w, uint16_t h, int16_t l, int1
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
TArray<uint8_t> FIMGZTexture::GetPalettedPixels(int conversion)
|
||||
TArray<uint8_t> FIMGZTexture::CreatePalettedPixels(int conversion)
|
||||
{
|
||||
FMemLump lump = Wads.ReadLump (SourceLump);
|
||||
const ImageHeader *imgz = (const ImageHeader *)lump.GetMem();
|
||||
|
|
|
@ -186,7 +186,7 @@ public:
|
|||
FJPEGTexture (int lumpnum, int width, int height);
|
||||
|
||||
int CopyPixels(FBitmap *bmp, int conversion) override;
|
||||
TArray<uint8_t> GetPalettedPixels(int conversion) override;
|
||||
TArray<uint8_t> CreatePalettedPixels(int conversion) override;
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
|
@ -260,7 +260,7 @@ FJPEGTexture::FJPEGTexture (int lumpnum, int width, int height)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
TArray<uint8_t> FJPEGTexture::GetPalettedPixels(int conversion)
|
||||
TArray<uint8_t> FJPEGTexture::CreatePalettedPixels(int conversion)
|
||||
{
|
||||
auto lump = Wads.OpenLumpReader (SourceLump);
|
||||
JSAMPLE *buff = NULL;
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#include "image.h"
|
||||
#include "multipatchtexture.h"
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FMultiPatchTexture :: FMultiPatchTexture
|
||||
|
@ -142,7 +143,8 @@ static uint8_t *GetBlendMap(PalEntry blend, uint8_t *blendwork)
|
|||
|
||||
void FMultiPatchTexture::CopyToBlock(uint8_t *dest, int dwidth, int dheight, FImageSource *source, int xpos, int ypos, int rotate, const uint8_t *translation, int style)
|
||||
{
|
||||
auto image = source->GetPalettedPixels(style); // should use composition cache
|
||||
auto cimage = source->GetCachedPalettedPixels(style); // should use composition cache
|
||||
auto &image = cimage.Pixels;
|
||||
const uint8_t *pixels = image.Data();
|
||||
int srcwidth = source->GetWidth();
|
||||
int srcheight = source->GetHeight();
|
||||
|
@ -188,7 +190,7 @@ void FMultiPatchTexture::CopyToBlock(uint8_t *dest, int dwidth, int dheight, FIm
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
TArray<uint8_t> FMultiPatchTexture::GetPalettedPixels(int conversion)
|
||||
TArray<uint8_t> FMultiPatchTexture::CreatePalettedPixels(int conversion)
|
||||
{
|
||||
int numpix = Width * Height;
|
||||
uint8_t blendwork[256];
|
||||
|
@ -324,3 +326,29 @@ int FMultiPatchTexture::CopyPixels(FBitmap *bmp, int conversion)
|
|||
return retv;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FMultiPatchTexture::CollectForPrecache(PrecacheInfo &info, bool requiretruecolor)
|
||||
{
|
||||
FImageSource::CollectForPrecache(info, requiretruecolor);
|
||||
|
||||
if (!requiretruecolor)
|
||||
{
|
||||
requiretruecolor = bComplex;
|
||||
|
||||
if (!requiretruecolor) for (int i = 0; i < NumParts; ++i)
|
||||
{
|
||||
if (Parts[i].op != OP_COPY) requiretruecolor = true;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < NumParts; ++i)
|
||||
{
|
||||
Parts[i].Image->CollectForPrecache(info, requiretruecolor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -39,8 +39,10 @@ protected:
|
|||
|
||||
// The getters must optionally redirect if it's a simple one-patch texture.
|
||||
int CopyPixels(FBitmap *bmp, int conversion) override;
|
||||
TArray<uint8_t> GetPalettedPixels(int conversion) override;
|
||||
TArray<uint8_t> CreatePalettedPixels(int conversion) override;
|
||||
void CopyToBlock(uint8_t *dest, int dwidth, int dheight, FImageSource *source, int xpos, int ypos, int rotate, const uint8_t *translation, int style);
|
||||
void CollectForPrecache(PrecacheInfo &info, bool requiretruecolor);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ class FPatchTexture : public FImageSource
|
|||
bool isalpha = false;
|
||||
public:
|
||||
FPatchTexture (int lumpnum, patch_t *header, bool isalphatex);
|
||||
TArray<uint8_t> GetPalettedPixels(int conversion) override;
|
||||
TArray<uint8_t> CreatePalettedPixels(int conversion) override;
|
||||
int CopyPixels(FBitmap *bmp, int conversion) override;
|
||||
void DetectBadPatches();
|
||||
};
|
||||
|
@ -163,7 +163,7 @@ FPatchTexture::FPatchTexture (int lumpnum, patch_t * header, bool isalphatex)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
TArray<uint8_t> FPatchTexture::GetPalettedPixels(int conversion)
|
||||
TArray<uint8_t> FPatchTexture::CreatePalettedPixels(int conversion)
|
||||
{
|
||||
uint8_t *remap, remaptable[256];
|
||||
int numspans;
|
||||
|
|
|
@ -93,7 +93,7 @@ protected:
|
|||
void ReadPCX8bits (uint8_t *dst, FileReader & lump, PCXHeader *hdr);
|
||||
void ReadPCX24bits (uint8_t *dst, FileReader & lump, PCXHeader *hdr, int planes);
|
||||
|
||||
TArray<uint8_t> GetPalettedPixels(int conversion) override;
|
||||
TArray<uint8_t> CreatePalettedPixels(int conversion) override;
|
||||
};
|
||||
|
||||
|
||||
|
@ -358,7 +358,7 @@ void FPCXTexture::ReadPCX24bits (uint8_t *dst, FileReader & lump, PCXHeader *hdr
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
TArray<uint8_t> FPCXTexture::GetPalettedPixels(int conversion)
|
||||
TArray<uint8_t> FPCXTexture::CreatePalettedPixels(int conversion)
|
||||
{
|
||||
uint8_t PaletteMap[256];
|
||||
PCXHeader header;
|
||||
|
|
|
@ -55,7 +55,7 @@ public:
|
|||
~FPNGTexture();
|
||||
|
||||
int CopyPixels(FBitmap *bmp, int conversion) override;
|
||||
TArray<uint8_t> GetPalettedPixels(int conversion) override;
|
||||
TArray<uint8_t> CreatePalettedPixels(int conversion) override;
|
||||
|
||||
protected:
|
||||
void ReadAlphaRemap(FileReader *lump, uint8_t *alpharemap);
|
||||
|
@ -367,7 +367,7 @@ void FPNGTexture::ReadAlphaRemap(FileReader *lump, uint8_t *alpharemap)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
TArray<uint8_t> FPNGTexture::GetPalettedPixels(int conversion)
|
||||
TArray<uint8_t> FPNGTexture::CreatePalettedPixels(int conversion)
|
||||
{
|
||||
FileReader *lump;
|
||||
FileReader lfr;
|
||||
|
|
|
@ -54,7 +54,7 @@ class FRawPageTexture : public FImageSource
|
|||
int mPaletteLump = -1;
|
||||
public:
|
||||
FRawPageTexture (int lumpnum);
|
||||
TArray<uint8_t> GetPalettedPixels(int conversion) override;
|
||||
TArray<uint8_t> CreatePalettedPixels(int conversion) override;
|
||||
int CopyPixels(FBitmap *bmp, int conversion) override;
|
||||
};
|
||||
|
||||
|
@ -173,7 +173,7 @@ FRawPageTexture::FRawPageTexture (int lumpnum)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
TArray<uint8_t> FRawPageTexture::GetPalettedPixels(int conversion)
|
||||
TArray<uint8_t> FRawPageTexture::CreatePalettedPixels(int conversion)
|
||||
{
|
||||
FMemLump lump = Wads.ReadLump (SourceLump);
|
||||
const uint8_t *source = (const uint8_t *)lump.GetMem();
|
||||
|
|
|
@ -100,7 +100,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
TArray<uint8_t> GetPalettedPixels(int conversion) override
|
||||
TArray<uint8_t> CreatePalettedPixels(int conversion) override
|
||||
{
|
||||
TArray<uint8_t> Pix(512, true);
|
||||
if (conversion == luminance)
|
||||
|
|
|
@ -85,7 +85,7 @@ public:
|
|||
|
||||
protected:
|
||||
void ReadCompressed(FileReader &lump, uint8_t * buffer, int bytesperpixel);
|
||||
TArray<uint8_t> GetPalettedPixels(int conversion) override;
|
||||
TArray<uint8_t> CreatePalettedPixels(int conversion) override;
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
|
@ -179,7 +179,7 @@ void FTGATexture::ReadCompressed(FileReader &lump, uint8_t * buffer, int bytespe
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
TArray<uint8_t> FTGATexture::GetPalettedPixels(int conversion)
|
||||
TArray<uint8_t> FTGATexture::CreatePalettedPixels(int conversion)
|
||||
{
|
||||
uint8_t PaletteMap[256];
|
||||
auto lump = Wads.OpenLumpReader (SourceLump);
|
||||
|
|
|
@ -43,6 +43,24 @@
|
|||
FMemArena FImageSource::ImageArena(32768);
|
||||
TArray<FImageSource *>FImageSource::ImageForLump;
|
||||
int FImageSource::NextID;
|
||||
static PrecacheInfo precacheInfo;
|
||||
|
||||
struct PrecacheDataPaletted
|
||||
{
|
||||
TArray<uint8_t> Pixels;
|
||||
int RefCount;
|
||||
int ImageID;
|
||||
};
|
||||
|
||||
struct PrecacheDataRgba
|
||||
{
|
||||
FBitmap Pixels;
|
||||
int ImageID;
|
||||
};
|
||||
|
||||
// TMap doesn't handle this kind of data well. std::map neither. The linear search is still faster, even for a few 100 entries because it doesn't have to access the heap as often..
|
||||
TArray<PrecacheDataPaletted> precacheDataPaletted;
|
||||
TArray<PrecacheDataRgba> precacheDataRgba;
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
|
@ -50,13 +68,97 @@ int FImageSource::NextID;
|
|||
//
|
||||
//===========================================================================
|
||||
|
||||
TArray<uint8_t> FImageSource::GetPalettedPixels(int conversion)
|
||||
TArray<uint8_t> FImageSource::CreatePalettedPixels(int conversion)
|
||||
{
|
||||
TArray<uint8_t> Pixels(Width * Height, true);
|
||||
memset(Pixels.Data(), 0, Width * Height);
|
||||
return Pixels;
|
||||
}
|
||||
|
||||
PalettedPixels FImageSource::GetCachedPalettedPixels(int conversion)
|
||||
{
|
||||
PalettedPixels ret;
|
||||
|
||||
FString name;
|
||||
Wads.GetLumpName(name, SourceLump);
|
||||
if (name.CompareNoCase("W_136") == 0)
|
||||
{
|
||||
int a = 0;
|
||||
}
|
||||
|
||||
std::pair<int, int> *info = nullptr;
|
||||
auto imageID = ImageID;
|
||||
|
||||
// Do we have this image in the cache?
|
||||
unsigned index = precacheDataPaletted.FindEx([=](PrecacheDataPaletted &entry) { return entry.ImageID == imageID; });
|
||||
if (index < precacheDataPaletted.Size())
|
||||
{
|
||||
auto cache = &precacheDataPaletted[index];
|
||||
|
||||
if (cache->RefCount > 1)
|
||||
{
|
||||
Printf("returning reference to %s, refcount = %d\n", name.GetChars(), cache->RefCount);
|
||||
ret.Pixels.Set(cache->Pixels.Data(), cache->Pixels.Size());
|
||||
cache->RefCount--;
|
||||
}
|
||||
else if (cache->Pixels.Size() > 0)
|
||||
{
|
||||
Printf("returning contents of %s, refcount = %d\n", name.GetChars(), cache->RefCount);
|
||||
ret.PixelStore = std::move(cache->Pixels);
|
||||
ret.Pixels.Set(ret.PixelStore.Data(), ret.PixelStore.Size());
|
||||
precacheDataPaletted.Delete(index);
|
||||
}
|
||||
else
|
||||
{
|
||||
Printf("something bad happened for %s, refcount = %d\n", name.GetChars(), cache->RefCount);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The image wasn't cached. Now there's two possibilities:
|
||||
auto info = precacheInfo.CheckKey(ImageID);
|
||||
if (!info || info->second <= 1 || conversion != normal)
|
||||
{
|
||||
// This is either the only copy needed or some access outside the caching block. In these cases create a new one and directly return it.
|
||||
Printf("returning fresh copy of %s\n", name.GetChars());
|
||||
ret.PixelStore = CreatePalettedPixels(conversion);
|
||||
ret.Pixels.Set(ret.PixelStore.Data(), ret.PixelStore.Size());
|
||||
}
|
||||
else
|
||||
{
|
||||
Printf("creating cached entry for %s, refcount = %d\n", name.GetChars(), info->second);
|
||||
// This is the first time it gets accessed and needs to be placed in the cache.
|
||||
PrecacheDataPaletted *pdp = &precacheDataPaletted[precacheDataPaletted.Reserve(1)];
|
||||
|
||||
pdp->ImageID = imageID;
|
||||
pdp->RefCount = info->second - 1;
|
||||
info->second = 0;
|
||||
pdp->Pixels = CreatePalettedPixels(normal);
|
||||
ret.Pixels.Set(pdp->Pixels.Data(), pdp->Pixels.Size());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
TArray<uint8_t> FImageSource::GetPalettedPixels(int conversion)
|
||||
{
|
||||
auto pix = GetCachedPalettedPixels(conversion);
|
||||
if (pix.ownsPixels())
|
||||
{
|
||||
// return the pixel store of the returned data directly if this was the last reference.
|
||||
auto array = std::move(pix.PixelStore);
|
||||
return array;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If there are pending references, make a copy.
|
||||
TArray<uint8_t> array(pix.Pixels.Size(), true);
|
||||
memcpy(array.Data(), pix.Pixels.Data(), array.Size());
|
||||
return array;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
|
@ -75,7 +177,7 @@ int FImageSource::CopyPixels(FBitmap *bmp, int conversion)
|
|||
if (conversion == luminance) conversion = normal; // luminance images have no use as an RGB source.
|
||||
PalEntry *palette = screen->GetPalette();
|
||||
for(int i=1;i<256;i++) palette[i].a = 255; // set proper alpha values
|
||||
auto ppix = GetPalettedPixels(conversion); // should use composition cache
|
||||
auto ppix = CreatePalettedPixels(conversion);
|
||||
bmp->CopyPixelData(0, 0, ppix.Data(), Width, Height, Height, 1, 0, palette, nullptr);
|
||||
for(int i=1;i<256;i++) palette[i].a = 0;
|
||||
return 0;
|
||||
|
@ -83,11 +185,54 @@ int FImageSource::CopyPixels(FBitmap *bmp, int conversion)
|
|||
|
||||
int FImageSource::CopyTranslatedPixels(FBitmap *bmp, PalEntry *remap)
|
||||
{
|
||||
auto ppix = GetPalettedPixels(false); // should use composition cache
|
||||
auto ppix = CreatePalettedPixels(false);
|
||||
bmp->CopyPixelData(0, 0, ppix.Data(), Width, Height, Height, 1, 0, remap, nullptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FImageSource::CollectForPrecache(PrecacheInfo &info, bool requiretruecolor)
|
||||
{
|
||||
auto val = info.CheckKey(ImageID);
|
||||
bool tc = requiretruecolor || V_IsTrueColor();
|
||||
if (val)
|
||||
{
|
||||
val->first += tc;
|
||||
val->second += !tc;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto pair = std::make_pair(tc, !tc);
|
||||
info.Insert(ImageID, pair);
|
||||
}
|
||||
}
|
||||
|
||||
void FImageSource::BeginPrecaching()
|
||||
{
|
||||
precacheInfo.Clear();
|
||||
}
|
||||
|
||||
void FImageSource::EndPrecaching()
|
||||
{
|
||||
precacheDataPaletted.Clear();
|
||||
precacheDataRgba.Clear();
|
||||
}
|
||||
|
||||
void FImageSource::RegisterForPrecache(FImageSource *img)
|
||||
{
|
||||
img->CollectForPrecache(precacheInfo);
|
||||
}
|
||||
|
||||
FBitmap FImageSource::GetPixelsWithCache(int conversion)
|
||||
{
|
||||
return FBitmap();
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
|
|
@ -5,6 +5,21 @@
|
|||
#include "textures/bitmap.h"
|
||||
#include "memarena.h"
|
||||
|
||||
class FImageSource;
|
||||
using PrecacheInfo = TMap<int, std::pair<int, int>>;
|
||||
|
||||
struct PalettedPixels
|
||||
{
|
||||
friend class FImageSource;
|
||||
TArrayView<uint8_t> Pixels;
|
||||
private:
|
||||
TArray<uint8_t> PixelStore;
|
||||
|
||||
bool ownsPixels() const
|
||||
{
|
||||
return Pixels.Data() == PixelStore.Data();
|
||||
}
|
||||
};
|
||||
|
||||
// This represents a naked image. It has no high level logic attached to it.
|
||||
// All it can do is provide raw image data to its users.
|
||||
|
@ -41,13 +56,27 @@ public:
|
|||
bool bMasked = true; // Image (might) have holes (Assume true unless proven otherwise!)
|
||||
int8_t bTranslucent = -1; // Image has pixels with a non-0/1 value. (-1 means the user needs to do a real check)
|
||||
|
||||
// Returns the whole texture, paletted and true color versions respectively.
|
||||
virtual TArray<uint8_t> GetPalettedPixels(int conversion); // 'noremap0' will only be looked at by FPatchTexture and forwarded by FMultipatchTexture.
|
||||
|
||||
// 'noremap0' will only be looked at by FPatchTexture and forwarded by FMultipatchTexture.
|
||||
|
||||
// Always creates a new pixel buffer for the texture
|
||||
virtual TArray<uint8_t> CreatePalettedPixels(int conversion);
|
||||
|
||||
// Either returns a reference to the cache, or a newly created item. The return of this has to be considered transient. If you need to store the result, use GetPalettedPixels
|
||||
PalettedPixels GetCachedPalettedPixels(int conversion);
|
||||
|
||||
// tries to get a buffer from the cache. If not available, create a new one. If further references are pending, create a copy.
|
||||
TArray<uint8_t> GetPalettedPixels(int conversion);
|
||||
|
||||
virtual int CopyPixels(FBitmap *bmp, int conversion); // This will always ignore 'luminance'.
|
||||
int CopyTranslatedPixels(FBitmap *bmp, PalEntry *remap);
|
||||
static void ClearImages() { ImageArena.FreeAll(); ImageForLump.Clear(); NextID = 0; }
|
||||
static FImageSource * FImageSource::GetImage(int lumpnum, ETextureType usetype);
|
||||
|
||||
// These functions either allocate a new buffer or reuse the last one, if its reference count was greater than 1 when last used.
|
||||
FBitmap GetPixelsWithCache(int conversion);
|
||||
|
||||
|
||||
// Conversion option
|
||||
enum EType
|
||||
{
|
||||
|
@ -59,9 +88,6 @@ public:
|
|||
FImageSource(int sourcelump = -1) : SourceLump(sourcelump) { ImageID = ++NextID; }
|
||||
virtual ~FImageSource() {}
|
||||
|
||||
// Creates an image from the given lump.
|
||||
static FImageSource *CreateImageSource(int lumpnum);
|
||||
|
||||
int GetWidth() const
|
||||
{
|
||||
return Width;
|
||||
|
@ -91,6 +117,11 @@ public:
|
|||
{
|
||||
return bUseGamePalette;
|
||||
}
|
||||
|
||||
virtual void CollectForPrecache(PrecacheInfo &info, bool requiretruecolor = false);
|
||||
static void BeginPrecaching();
|
||||
static void EndPrecaching();
|
||||
static void RegisterForPrecache(FImageSource *img);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -307,14 +307,6 @@ public:
|
|||
/*virtual*/ FBitmap GetBgraBitmap(PalEntry *remap, int *trans = nullptr);
|
||||
|
||||
public:
|
||||
/*
|
||||
static void FlipSquareBlock (uint8_t *block, int x, int y);
|
||||
static void FlipSquareBlockBgra (uint32_t *block, int x, int y);
|
||||
static void FlipSquareBlockRemap (uint8_t *block, int x, int y, const uint8_t *remap);
|
||||
static void FlipNonSquareBlock (uint8_t *blockto, const uint8_t *blockfrom, int x, int y, int srcpitch);
|
||||
static void FlipNonSquareBlockBgra (uint32_t *blockto, const uint32_t *blockfrom, int x, int y, int srcpitch);
|
||||
static void FlipNonSquareBlockRemap (uint8_t *blockto, const uint8_t *blockfrom, int x, int y, int srcpitch, const uint8_t *remap);
|
||||
*/
|
||||
static bool SmoothEdges(unsigned char * buffer,int w, int h);
|
||||
static PalEntry averageColor(const uint32_t *data, int size, int maxout);
|
||||
|
||||
|
@ -436,7 +428,7 @@ protected:
|
|||
|
||||
virtual void ResolvePatches() {}
|
||||
|
||||
virtual void SetFrontSkyLayer();
|
||||
void SetFrontSkyLayer();
|
||||
|
||||
static void InitGrayMap();
|
||||
|
||||
|
@ -645,11 +637,12 @@ private:
|
|||
TArray<int> FirstTextureForFile;
|
||||
TArray<TArray<uint8_t> > BuildTileData;
|
||||
|
||||
TArray<FAnimDef *> mAnimations;
|
||||
TArray<FSwitchDef *> mSwitchDefs;
|
||||
TArray<FDoorAnimation> mAnimatedDoors;
|
||||
|
||||
public:
|
||||
TArray<FAnimDef *> mAnimations;
|
||||
|
||||
bool HasGlobalBrightmap;
|
||||
FRemapTable GlobalBrightmap;
|
||||
short sintable[2048]; // for texture warping
|
||||
|
|
|
@ -428,6 +428,7 @@ public:
|
|||
virtual void CleanForRestart() {}
|
||||
virtual void SetTextureFilterMode() {}
|
||||
virtual IHardwareTexture *CreateHardwareTexture(FTexture *tex) { return nullptr; }
|
||||
virtual bool CheckPrecacheMaterial(FMaterial *mat) { return true; }
|
||||
virtual void PrecacheMaterial(FMaterial *mat, int translation) {}
|
||||
virtual FModelRenderer *CreateModelRenderer(int mli) { return nullptr; }
|
||||
virtual void UnbindTexUnit(int no) {}
|
||||
|
|
Loading…
Reference in a new issue