2020-05-24 17:12:22 +00:00
# pragma once
# include "tarray.h"
# include "hw_ihwtexture.h"
# include "palettecontainer.h"
struct FTextureBuffer ;
class IHardwareTexture ;
2020-05-25 21:59:07 +00:00
enum ECreateTexBufferFlags
{
CTF_Expand = 1 , // create buffer with a one-pixel wide border
CTF_Upscale = 2 , // Upscale the texture
CTF_CreateMask = 3 , // Flags that are relevant for hardware texture creation.
2020-09-28 19:24:08 +00:00
CTF_Indexed = 4 , // Tell the backend to create an indexed texture.
2020-09-27 08:39:10 +00:00
CTF_CheckOnly = 8 , // Only runs the code to get a content ID but does not create a texture. Can be used to access a caching system for the hardware textures.
2020-09-28 19:24:08 +00:00
CTF_ProcessData = 16 , // run postprocessing on the generated buffer. This is only needed when using the data for a hardware texture.
2020-05-25 21:59:07 +00:00
} ;
2020-05-24 17:12:22 +00:00
class FHardwareTextureContainer
{
public :
enum
{
MAX_TEXTURES = 16
} ;
private :
struct TranslatedTexture
{
IHardwareTexture * hwTexture = nullptr ;
int translation = 0 ;
2020-05-25 21:59:07 +00:00
bool precacheMarker ; // This is used to check whether a texture has been hit by the precacher, so that the cleanup code can delete the unneeded ones.
2020-05-24 17:12:22 +00:00
void Delete ( )
{
if ( hwTexture ) delete hwTexture ;
hwTexture = nullptr ;
}
~ TranslatedTexture ( )
{
Delete ( ) ;
}
2020-05-25 21:59:07 +00:00
void MarkForPrecache ( bool on )
{
precacheMarker = on ;
}
bool isMarkedForPreache ( ) const
{
return precacheMarker ;
}
2020-05-24 17:12:22 +00:00
} ;
private :
2020-05-25 21:59:07 +00:00
TranslatedTexture hwDefTex [ 4 ] ;
2020-05-24 17:12:22 +00:00
TArray < TranslatedTexture > hwTex_Translated ;
2020-05-25 21:59:07 +00:00
TranslatedTexture * GetTexID ( int translation , int scaleflags )
2020-05-24 17:12:22 +00:00
{
2020-05-24 22:31:05 +00:00
// 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 )
{
2021-05-24 11:16:50 +00:00
if ( ! IsLuminosityTranslation ( translation ) )
{
auto remap = GPalette . TranslationToTable ( translation ) ;
translation = remap = = nullptr ? 0 : remap - > Index ;
}
else
{
// only needs to preserve the color range plus an identifier for marking this a luminosity translation.
translation = ( ( translation > > 16 ) & 0x3fff ) | 0xff0000 ;
}
2020-05-24 22:31:05 +00:00
}
else translation & = ~ 0x7fffffff ;
2020-05-24 17:12:22 +00:00
2020-05-25 21:59:07 +00:00
if ( translation = = 0 & & ! ( scaleflags & CTF_Upscale ) )
2020-05-24 17:12:22 +00:00
{
2020-05-25 21:59:07 +00:00
return & hwDefTex [ scaleflags ] ;
2020-05-24 17:12:22 +00:00
}
2020-05-25 21:59:07 +00:00
translation | = ( scaleflags < < 24 ) ;
2020-05-24 17:12:22 +00:00
// 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 :
2020-05-25 21:59:07 +00:00
void Clean ( )
2020-05-24 17:12:22 +00:00
{
2020-05-25 21:59:07 +00:00
hwDefTex [ 0 ] . Delete ( ) ;
hwDefTex [ 1 ] . Delete ( ) ;
hwTex_Translated . Clear ( ) ;
2020-05-24 17:12:22 +00:00
}
2020-05-25 21:59:07 +00:00
IHardwareTexture * GetHardwareTexture ( int translation , int scaleflags )
2020-05-24 17:12:22 +00:00
{
2020-05-25 21:59:07 +00:00
auto tt = GetTexID ( translation , scaleflags ) ;
2020-05-24 17:12:22 +00:00
return tt - > hwTexture ;
}
2020-05-25 21:59:07 +00:00
void AddHardwareTexture ( int translation , int scaleflags , IHardwareTexture * tex )
2020-05-24 17:12:22 +00:00
{
2020-05-25 21:59:07 +00:00
auto tt = GetTexID ( translation , scaleflags ) ;
2020-05-24 17:12:22 +00:00
tt - > Delete ( ) ;
tt - > hwTexture = tex ;
}
//===========================================================================
//
// Deletes all allocated resources and considers translations
//
//===========================================================================
2020-05-25 21:59:07 +00:00
void CleanUnused ( )
2020-05-24 17:12:22 +00:00
{
2020-05-25 21:59:07 +00:00
for ( auto & tt : hwDefTex )
2020-05-24 17:12:22 +00:00
{
2020-05-25 21:59:07 +00:00
if ( ! tt . isMarkedForPreache ( ) ) tt . Delete ( ) ;
2020-05-24 17:12:22 +00:00
}
for ( int i = hwTex_Translated . Size ( ) - 1 ; i > = 0 ; i - - )
{
2020-05-25 21:59:07 +00:00
auto & tt = hwTex_Translated [ i ] ;
if ( ! tt . isMarkedForPreache ( ) )
2020-05-24 17:12:22 +00:00
{
hwTex_Translated . Delete ( i ) ;
}
}
}
2020-05-25 21:59:07 +00:00
void UnmarkAll ( )
{
for ( auto & tt : hwDefTex )
{
if ( ! tt . isMarkedForPreache ( ) ) tt . MarkForPrecache ( false ) ;
}
for ( auto & tt : hwTex_Translated )
{
if ( ! tt . isMarkedForPreache ( ) ) tt . MarkForPrecache ( false ) ;
}
}
void MarkForPrecache ( int translation , int scaleflags )
{
auto tt = GetTexID ( translation , scaleflags ) ;
tt - > MarkForPrecache ( true ) ;
}
2020-05-24 17:12:22 +00:00
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 ) ;
}
} ;