raze/source/common/textures/hw_texcontainer.h
Christoph Oelckers 758e4ad7cb - stripped down the palette manager in the GL backend and let it use the data that's managed elsewhere.
This class is only needed to manage the palette textures used by the indexed render mode, all the rest is available globally.
2020-05-25 00:31:55 +02:00

143 lines
3.3 KiB
C++

#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);
}
};