Ported skincolor cache management from the secondcolor branch
Adjusted R_GetTranslationRemap to use a similar caching scheme
Made sure that if a skincolor was updated, then related translations would be rebuilt
This commit is contained in:
Lactozilla 2024-01-20 01:47:03 -03:00
parent 9851ec56cf
commit 8cff33e681
5 changed files with 105 additions and 68 deletions

View file

@ -26,9 +26,6 @@
#include "taglist.h" #include "taglist.h"
// Amount of colors in the palette
#define NUM_PALETTE_ENTRIES 256
// //
// ClipWallSegment // ClipWallSegment
// Clips the given range of columns // Clips the given range of columns

View file

@ -125,49 +125,37 @@ UINT32 nflatxshift, nflatyshift, nflatshiftup, nflatmask;
// TRANSLATION COLORMAP CODE // TRANSLATION COLORMAP CODE
// ========================================================================= // =========================================================================
enum static colorcache_t **translationtablecache[TT_CACHE_SIZE] = {NULL};
{
DEFAULT_TT_CACHE_INDEX,
BOSS_TT_CACHE_INDEX,
METALSONIC_TT_CACHE_INDEX,
ALLWHITE_TT_CACHE_INDEX,
RAINBOW_TT_CACHE_INDEX,
BLINK_TT_CACHE_INDEX,
DASHMODE_TT_CACHE_INDEX,
TT_CACHE_SIZE
};
static UINT8 **translationtablecache[TT_CACHE_SIZE] = {NULL};
static UINT8 **skintranslationcache[NUM_PALETTE_ENTRIES] = {NULL};
boolean skincolor_modified[MAXSKINCOLORS]; boolean skincolor_modified[MAXSKINCOLORS];
static INT32 TranslationToCacheIndex(INT32 translation) static INT32 SkinToCacheIndex(INT32 translation)
{ {
switch (translation) switch (translation)
{ {
case TC_DEFAULT: return DEFAULT_TT_CACHE_INDEX;
case TC_BOSS: return BOSS_TT_CACHE_INDEX; case TC_BOSS: return BOSS_TT_CACHE_INDEX;
case TC_METALSONIC: return METALSONIC_TT_CACHE_INDEX; case TC_METALSONIC: return METALSONIC_TT_CACHE_INDEX;
case TC_ALLWHITE: return ALLWHITE_TT_CACHE_INDEX; case TC_ALLWHITE: return ALLWHITE_TT_CACHE_INDEX;
case TC_RAINBOW: return RAINBOW_TT_CACHE_INDEX; case TC_RAINBOW: return RAINBOW_TT_CACHE_INDEX;
case TC_BLINK: return BLINK_TT_CACHE_INDEX; case TC_BLINK: return BLINK_TT_CACHE_INDEX;
case TC_DASHMODE: return DASHMODE_TT_CACHE_INDEX; case TC_DASHMODE: return DASHMODE_TT_CACHE_INDEX;
default: return DEFAULT_TT_CACHE_INDEX; default: return translation;
} }
} }
static INT32 CacheIndexToTranslation(INT32 index) static INT32 CacheIndexToSkin(INT32 index)
{ {
switch (index) switch (index)
{ {
case DEFAULT_TT_CACHE_INDEX: return TC_DEFAULT;
case BOSS_TT_CACHE_INDEX: return TC_BOSS; case BOSS_TT_CACHE_INDEX: return TC_BOSS;
case METALSONIC_TT_CACHE_INDEX: return TC_METALSONIC; case METALSONIC_TT_CACHE_INDEX: return TC_METALSONIC;
case ALLWHITE_TT_CACHE_INDEX: return TC_ALLWHITE; case ALLWHITE_TT_CACHE_INDEX: return TC_ALLWHITE;
case RAINBOW_TT_CACHE_INDEX: return TC_RAINBOW; case RAINBOW_TT_CACHE_INDEX: return TC_RAINBOW;
case BLINK_TT_CACHE_INDEX: return TC_BLINK; case BLINK_TT_CACHE_INDEX: return TC_BLINK;
case DASHMODE_TT_CACHE_INDEX: return TC_DASHMODE; case DASHMODE_TT_CACHE_INDEX: return TC_DASHMODE;
default: return TC_DEFAULT; default: return index;
} }
} }
@ -553,23 +541,22 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 translatio
*/ */
UINT8* R_GetTranslationColormap(INT32 skinnum, skincolornum_t color, UINT8 flags) UINT8* R_GetTranslationColormap(INT32 skinnum, skincolornum_t color, UINT8 flags)
{ {
UINT8 ***cache = NULL; colorcache_t *ret;
INT32 index, starttranscolor; INT32 index = 0;
UINT8 *ret; INT32 starttranscolor = DEFAULT_STARTTRANSCOLOR;
// Adjust if we want the default colormap // Adjust if we want the default colormap
if (skinnum >= numskins) if (skinnum >= numskins)
I_Error("Invalid skin number %d", skinnum); I_Error("Invalid skin number %d", skinnum);
else if (skinnum >= 0) else if (skinnum >= 0)
{ {
cache = skintranslationcache; index = skins[skinnum]->skinnum;
starttranscolor = index = skins[skinnum]->starttranscolor; starttranscolor = skins[skinnum]->starttranscolor;
} }
else if (skinnum <= TC_DEFAULT) else if (skinnum <= TC_DEFAULT)
{ {
cache = translationtablecache; // Do default translation
starttranscolor = DEFAULT_STARTTRANSCOLOR; index = SkinToCacheIndex(skinnum);
index = TranslationToCacheIndex(skinnum);
} }
else else
I_Error("Invalid translation %d", skinnum); I_Error("Invalid translation %d", skinnum);
@ -577,41 +564,48 @@ UINT8* R_GetTranslationColormap(INT32 skinnum, skincolornum_t color, UINT8 flags
if (flags & GTC_CACHE) if (flags & GTC_CACHE)
{ {
// Allocate table for skin if necessary // Allocate table for skin if necessary
if (!cache[index]) if (!translationtablecache[index])
cache[index] = Z_Calloc(MAXSKINCOLORS * sizeof(UINT8**), PU_STATIC, NULL); translationtablecache[index] = Z_Calloc(MAXSKINCOLORS * sizeof(colorcache_t**), PU_STATIC, NULL);
// Get colormap // Get colormap
ret = cache[index][color]; ret = translationtablecache[index][color];
// Rebuild the cache if necessary // Rebuild the cache if necessary
if (skincolor_modified[color]) if (skincolor_modified[color])
{ {
INT32 i; // Moved up here so that R_UpdateTranslationRemaps doesn't cause a stack overflow,
// since in this situation, it will call R_GetTranslationColormap
for (i = 0; i < TT_CACHE_SIZE; i++)
if (translationtablecache[i] && translationtablecache[i][color])
R_GenerateTranslationColormap(translationtablecache[i][color], CacheIndexToTranslation(i), color, starttranscolor);
for (i = 0; i < NUM_PALETTE_ENTRIES; i++)
if (skintranslationcache[i] && skintranslationcache[i][color])
R_GenerateTranslationColormap(skintranslationcache[i][color], 0, color, i);
skincolor_modified[color] = false; skincolor_modified[color] = false;
for (unsigned i = 0; i < TT_CACHE_SIZE; i++)
{
if (translationtablecache[i])
{
colorcache_t *cache = translationtablecache[i][color];
if (cache)
{
R_GenerateTranslationColormap(cache->colors, CacheIndexToSkin(i), color, starttranscolor);
R_UpdateTranslationRemaps(color, i);
} }
} }
else ret = NULL; }
}
}
else
ret = NULL;
// Generate the colormap if necessary // Generate the colormap if necessary
if (!ret) if (!ret)
{ {
ret = Z_MallocAlign(NUM_PALETTE_ENTRIES, (flags & GTC_CACHE) ? PU_LEVEL : PU_STATIC, NULL, 8); ret = Z_Malloc(sizeof(colorcache_t), (flags & GTC_CACHE) ? PU_LEVEL : PU_STATIC, NULL);
R_GenerateTranslationColormap(ret, skinnum, color, starttranscolor); R_GenerateTranslationColormap(ret->colors, skinnum, color, starttranscolor);
// Cache the colormap if desired // Cache the colormap if desired
if (flags & GTC_CACHE) if (flags & GTC_CACHE)
cache[index][color] = ret; translationtablecache[index][color] = ret;
} }
return ret; return ret->colors;
} }
/** \brief Flushes cache of translation colormaps. /** \brief Flushes cache of translation colormaps.
@ -629,9 +623,6 @@ void R_FlushTranslationColormapCache(void)
for (i = 0; i < TT_CACHE_SIZE; i++) for (i = 0; i < TT_CACHE_SIZE; i++)
if (translationtablecache[i]) if (translationtablecache[i])
memset(translationtablecache[i], 0, MAXSKINCOLORS * sizeof(UINT8**)); memset(translationtablecache[i], 0, MAXSKINCOLORS * sizeof(UINT8**));
for (i = 0; i < NUM_PALETTE_ENTRIES; i++)
if (skintranslationcache[i])
memset(skintranslationcache[i], 0, MAXSKINCOLORS * sizeof(UINT8**));
} }
UINT16 R_GetColorByName(const char *name) UINT16 R_GetColorByName(const char *name)

View file

@ -117,6 +117,27 @@ enum
TC_DEFAULT TC_DEFAULT
}; };
// Amount of colors in the palette
#define NUM_PALETTE_ENTRIES 256
typedef struct colorcache_s
{
UINT8 colors[NUM_PALETTE_ENTRIES];
} colorcache_t;
enum
{
DEFAULT_TT_CACHE_INDEX = MAXSKINS,
BOSS_TT_CACHE_INDEX,
METALSONIC_TT_CACHE_INDEX,
ALLWHITE_TT_CACHE_INDEX,
RAINBOW_TT_CACHE_INDEX,
BLINK_TT_CACHE_INDEX,
DASHMODE_TT_CACHE_INDEX,
TT_CACHE_SIZE
};
// Custom player skin translation // Custom player skin translation
// Initialize color translation tables, for player rendering etc. // Initialize color translation tables, for player rendering etc.
UINT8* R_GetTranslationColormap(INT32 skinnum, skincolornum_t color, UINT8 flags); UINT8* R_GetTranslationColormap(INT32 skinnum, skincolornum_t color, UINT8 flags);

View file

@ -1103,6 +1103,17 @@ remaptable_t *R_GetTranslationByID(int id)
return paletteremaps[id]; return paletteremaps[id];
} }
static void R_ApplyTranslationRemap(remaptable_t *tr, UINT8 *remap, skincolornum_t skincolor, INT32 skinnum)
{
UINT8 *base_skincolor = R_GetTranslationColormap(skinnum, skincolor, GTC_CACHE);
for (unsigned i = 0; i < NUM_PALETTE_ENTRIES; i++)
remap[i] = base_skincolor[i];
for (unsigned i = 0; i < tr->num_sources; i++)
PaletteRemap_Apply(remap, &tr->sources[i]);
}
UINT8 *R_GetTranslationRemap(int id, skincolornum_t skincolor, INT32 skinnum) UINT8 *R_GetTranslationRemap(int id, skincolornum_t skincolor, INT32 skinnum)
{ {
remaptable_t *tr = R_GetTranslationByID(id); remaptable_t *tr = R_GetTranslationByID(id);
@ -1112,25 +1123,39 @@ UINT8 *R_GetTranslationRemap(int id, skincolornum_t skincolor, INT32 skinnum)
if (!tr->num_sources || skincolor == SKINCOLOR_NONE) if (!tr->num_sources || skincolor == SKINCOLOR_NONE)
return tr->remap; return tr->remap;
if (!tr->skincolor_remap) if (!tr->skincolor_remaps)
tr->skincolor_remap = Z_Calloc(NUM_PALETTE_ENTRIES * MAXSKINCOLORS, PU_LEVEL, &tr->skincolor_remap); Z_Calloc(sizeof(*tr->skincolor_remaps) * TT_CACHE_SIZE, PU_LEVEL, &tr->skincolor_remaps);
if (!tr->skincolor_remap[skincolor]) if (!tr->skincolor_remaps[skinnum])
tr->skincolor_remaps[skinnum] = Z_Calloc(NUM_PALETTE_ENTRIES * MAXSKINCOLORS, PU_LEVEL, NULL);
colorcache_t *cache = tr->skincolor_remaps[skinnum][skincolor];
if (!cache)
{ {
UINT8 *remap = Z_Calloc(NUM_PALETTE_ENTRIES, PU_LEVEL, NULL); cache = Z_Calloc(sizeof(colorcache_t), PU_LEVEL, NULL);
UINT8 *base_skincolor = R_GetTranslationColormap(skinnum, skincolor, GTC_CACHE); R_ApplyTranslationRemap(tr, cache->colors, skincolor, skinnum);
for (unsigned i = 0; i < NUM_PALETTE_ENTRIES; i++) tr->skincolor_remaps[skinnum][skincolor] = cache;
remap[i] = base_skincolor[i];
for (unsigned i = 0; i < tr->num_sources; i++)
PaletteRemap_Apply(remap, &tr->sources[i]);
tr->skincolor_remap[skincolor] = remap;
} }
return tr->skincolor_remap[skincolor]; return cache->colors;
}
static void R_UpdateTranslation(remaptable_t *tr, skincolornum_t skincolor, INT32 skinnum)
{
if (!tr->num_sources || !tr->skincolor_remaps || !tr->skincolor_remaps[skinnum])
return;
colorcache_t *cache = tr->skincolor_remaps[skinnum][skincolor];
if (cache)
R_ApplyTranslationRemap(tr, cache->colors, skincolor, skinnum);
}
void R_UpdateTranslationRemaps(skincolornum_t skincolor, INT32 skinnum)
{
for (unsigned i = 0; i < numpaletteremaps; i++)
R_UpdateTranslation(paletteremaps[i], skincolor, skinnum);
} }
boolean R_TranslationIsValid(int id) boolean R_TranslationIsValid(int id)

View file

@ -15,6 +15,8 @@
#include "doomdef.h" #include "doomdef.h"
#include "r_draw.h"
typedef enum typedef enum
{ {
REMAP_ADD_INDEXRANGE, REMAP_ADD_INDEXRANGE,
@ -58,16 +60,16 @@ typedef struct
typedef struct typedef struct
{ {
UINT8 remap[256]; UINT8 remap[NUM_PALETTE_ENTRIES];
unsigned num_entries; unsigned num_entries;
paletteremap_t *sources; paletteremap_t *sources;
unsigned num_sources; unsigned num_sources;
// A typical remap is 256 bytes long, and there is currently a maximum of 1182 skincolors. // A typical remap is 256 bytes long, and there is currently a maximum of 1182 skincolors, and 263 possible color cache entries.
// This means allocating (1182 * 256) bytes, which equals 302592, or ~302kb of memory for every translation. // This would mean allocating (1182 * 256 * 263) bytes, which equals 79581696 bytes, or ~79mb of memory for every remap.
// So we allocate a list instead. // So instead a few lists are allocated.
UINT8 **skincolor_remap; colorcache_t ***skincolor_remaps;
} remaptable_t; } remaptable_t;
void PaletteRemap_Init(void); void PaletteRemap_Init(void);
@ -85,6 +87,7 @@ const char *R_GetCustomTranslationName(unsigned id);
unsigned R_NumCustomTranslations(void); unsigned R_NumCustomTranslations(void);
remaptable_t *R_GetTranslationByID(int id); remaptable_t *R_GetTranslationByID(int id);
UINT8 *R_GetTranslationRemap(int id, skincolornum_t skincolor, INT32 skinnum); UINT8 *R_GetTranslationRemap(int id, skincolornum_t skincolor, INT32 skinnum);
void R_UpdateTranslationRemaps(skincolornum_t skincolor, INT32 skinnum);
boolean R_TranslationIsValid(int id); boolean R_TranslationIsValid(int id);
void R_ParseTrnslate(INT32 wadNum, UINT16 lumpnum); void R_ParseTrnslate(INT32 wadNum, UINT16 lumpnum);