raze/source/common/textures/hw_texcontainer.h

144 lines
3.3 KiB
C
Raw Normal View History

#pragma once
#include "tarray.h"
#include "hw_ihwtexture.h"
#include "palettecontainer.h"
struct FTextureBuffer;
class IHardwareTexture;
class FHardwareTextureContainer
{
public:
enum
{
MAX_TEXTURES = 16
};
private:
struct TranslatedTexture
{
IHardwareTexture *hwTexture = nullptr;
int translation = 0;
void Delete()
{
if (hwTexture) delete hwTexture;
hwTexture = nullptr;
}
void DeleteDescriptors()
{
if (hwTexture) hwTexture->DeleteDescriptors();
}
~TranslatedTexture()
{
Delete();
}
};
private:
TranslatedTexture hwDefTex[2];
TArray<TranslatedTexture> hwTex_Translated;
TranslatedTexture * GetTexID(int translation, bool expanded)
{
// Allow negative indices to pass through unchanged.
// This is needed for allowing the client to allocate slots that aren't matched to a palette, e.g. Build's indexed variants.
if (translation >= 0)
{
auto remap = GPalette.TranslationToTable(translation);
translation = remap == nullptr ? 0 : remap->Index;
}
else translation &= ~0x7fffffff;
if (translation == 0)
{
return &hwDefTex[expanded];
}
if (expanded) translation = -translation;
// normally there aren't more than very few different
// translations here so this isn't performance critical.
unsigned index = hwTex_Translated.FindEx([=](auto &element)
{
return element.translation == translation;
});
if (index < hwTex_Translated.Size())
{
return &hwTex_Translated[index];
}
int add = hwTex_Translated.Reserve(1);
auto item = &hwTex_Translated[add];
item->translation = translation;
return item;
}
public:
void Clean(bool cleannormal, bool cleanexpanded)
{
if (cleannormal) hwDefTex[0].Delete();
if (cleanexpanded) hwDefTex[1].Delete();
hwDefTex[0].DeleteDescriptors();
hwDefTex[1].DeleteDescriptors();
for (int i = hwTex_Translated.Size() - 1; i >= 0; i--)
{
if (cleannormal && hwTex_Translated[i].translation > 0) hwTex_Translated.Delete(i);
else if (cleanexpanded && hwTex_Translated[i].translation < 0) hwTex_Translated.Delete(i);
for (unsigned int j = 0; j < hwTex_Translated.Size(); j++)
hwTex_Translated[j].DeleteDescriptors();
}
}
IHardwareTexture * GetHardwareTexture(int translation, bool expanded)
{
auto tt = GetTexID(translation, expanded);
return tt->hwTexture;
}
void AddHardwareTexture(int translation, bool expanded, IHardwareTexture *tex)
{
auto tt = GetTexID(translation, expanded);
tt->Delete();
tt->hwTexture =tex;
}
//===========================================================================
//
// Deletes all allocated resources and considers translations
// This will only be called for sprites
//
//===========================================================================
void CleanUnused(SpriteHits &usedtranslations, bool expanded)
{
if (usedtranslations.CheckKey(0) == nullptr)
{
hwDefTex[expanded].Delete();
}
int fac = expanded ? -1 : 1;
for (int i = hwTex_Translated.Size()-1; i>= 0; i--)
{
if (usedtranslations.CheckKey(hwTex_Translated[i].translation * fac) == nullptr)
{
hwTex_Translated.Delete(i);
}
}
}
template<class T>
void Iterate(T callback)
{
for (auto & t : hwDefTex) if (t.hwTexture) callback(t.hwTexture);
for (auto & t : hwTex_Translated) if (t.hwTexture) callback(t.hwTexture);
}
};