mirror of
https://github.com/DrBeef/Raze.git
synced 2024-11-15 00:41:55 +00:00
- moved the palette management into the backend.
This commit is contained in:
parent
b1aaafb973
commit
734d8b7d1e
5 changed files with 278 additions and 57 deletions
|
@ -778,6 +778,7 @@ set (PCH_SOURCES
|
|||
glbackend/gl_samplers.cpp
|
||||
glbackend/gl_shader.cpp
|
||||
glbackend/glbackend.cpp
|
||||
glbackend/gl_palmanager.cpp
|
||||
|
||||
mact/src/animlib.cpp
|
||||
mact/src/control.cpp
|
||||
|
|
|
@ -136,8 +136,6 @@ static GLuint quadVertsID = 0;
|
|||
|
||||
#define PALSWAP_TEXTURE_SIZE 2048
|
||||
int32_t r_useindexedcolortextures = -1;
|
||||
static int32_t lastbasepal = -1;
|
||||
static FHardwareTexture *paletteTextureIDs[MAXBASEPALS];
|
||||
static FHardwareTexture *palswapTextureID = nullptr;
|
||||
|
||||
static inline float float_trans(uint32_t maskprops, uint8_t blend)
|
||||
|
@ -373,10 +371,8 @@ void polymost_glinit()
|
|||
{
|
||||
globalflags |= GLOBAL_NO_GL_TILESHADES; // This re-enables the old fading logic without re-adding the r_usetileshades variable. The entire thing will have to be done on a more abstract level anyway.
|
||||
|
||||
lastbasepal = -1;
|
||||
for (int basepalnum = 0; basepalnum < MAXBASEPALS; ++basepalnum)
|
||||
for (int basepalnum = 0; basepalnum < MAXBASEPALS; ++basepalnum)
|
||||
{
|
||||
paletteTextureIDs[basepalnum] = 0;
|
||||
uploadbasepalette(basepalnum);
|
||||
}
|
||||
palswapTextureID = 0;
|
||||
|
@ -705,14 +701,7 @@ void uploadbasepalette(int32_t basepalnum, bool transient) // transient palettes
|
|||
basepalWFullBrightInfo[i*4+3] = 0-(IsPaletteIndexFullbright(i) != 0);
|
||||
}
|
||||
|
||||
if (!paletteTextureIDs[basepalnum])
|
||||
{
|
||||
auto &p = paletteTextureIDs[basepalnum];
|
||||
p = GLInterface.NewTexture();
|
||||
p->CreateTexture(256, 1, false, false);
|
||||
p->SetSampler(Sampler2DNoFilter);
|
||||
}
|
||||
paletteTextureIDs[basepalnum]->LoadTexture(basepalWFullBrightInfo); // RGBA
|
||||
GLInterface.SetPaletteData(basepalnum, basepalWFullBrightInfo, transient);
|
||||
}
|
||||
|
||||
// Used by RRRA fog hackery - the only place changing the palswaps at run time.
|
||||
|
@ -1162,13 +1151,7 @@ static void polymost_updatePalette()
|
|||
|
||||
GLInterface.SetPalswap(globalpal);
|
||||
GLInterface.SetShade(globalshade, numshades);
|
||||
|
||||
//POGO: only bind the base pal once when it's swapped
|
||||
if (curbasepal != lastbasepal)
|
||||
{
|
||||
GLInterface.BindTexture(2, paletteTextureIDs[curbasepal], Sampler2DNoFilter);
|
||||
lastbasepal = curbasepal;
|
||||
}
|
||||
GLInterface.SetPalette(curbasepal);
|
||||
}
|
||||
|
||||
|
||||
|
|
211
source/glbackend/gl_palmanager.cpp
Normal file
211
source/glbackend/gl_palmanager.cpp
Normal file
|
@ -0,0 +1,211 @@
|
|||
/*
|
||||
** gl_palmanager.cpp
|
||||
** Palette management
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2019 Christoph Oelckers
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
**
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
#include "m_crc32.h"
|
||||
#include "glad/glad.h"
|
||||
#include "glbackend.h"
|
||||
#include "gl_samplers.h"
|
||||
#include "gl_shader.h"
|
||||
|
||||
#include "baselayer.h"
|
||||
#include "resourcefile.h"
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// The palette manager will contain all palettes being used for texture
|
||||
// creation. It is also responsible for creating palette textures for indexed
|
||||
// rendering.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
PaletteManager::~PaletteManager()
|
||||
{
|
||||
DeleteAll();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void PaletteManager::DeleteAll()
|
||||
{
|
||||
for (auto& pal : palettes)
|
||||
{
|
||||
if (pal.paltexture) delete pal.paltexture;
|
||||
}
|
||||
if (transientpalette.paltexture) delete transientpalette.paltexture;
|
||||
transientpalette.paltexture = nullptr;
|
||||
transientpalette.crc32 = -1;
|
||||
palettes.Reset();
|
||||
palswaps.Reset();
|
||||
lastindex = -1;
|
||||
memset(palettemap, 0, sizeof(palettemap));
|
||||
memset(palswapmap, 0, sizeof(palswapmap));
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Adds a new palette while looking for duplicates.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
unsigned PaletteManager::FindPalette(const uint8_t *paldata)
|
||||
{
|
||||
auto crc32 = CalcCRC32(paldata, 1024);
|
||||
for (unsigned int i = 0; i< palettes.Size(); i++)
|
||||
{
|
||||
if (crc32 == palettes[i].crc32)
|
||||
{
|
||||
if (!memcmp(paldata, palettes[i].colors, 1024))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
PaletteData pd;
|
||||
memcpy(pd.colors, paldata, 1024);
|
||||
pd.crc32 = crc32;
|
||||
pd.paltexture = nullptr;
|
||||
return palettes.Push(pd);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void PaletteManager::SetPalette(int index, const uint8_t* data, bool transient)
|
||||
{
|
||||
// New palettes may only be added if declared transient or on startup.
|
||||
// Otherwise this would require a renderer reset to flush out the textures affected by the change.
|
||||
|
||||
if (index < 0 || index > 255) return; // invalid index - ignore.
|
||||
if (transient)
|
||||
{
|
||||
// Transient palettes do not get stored in the list because it is assumed that they won't be needed for long.
|
||||
// Only clear the texture if the palette is different.
|
||||
if (memcmp(data, transientpalette.colors, 1024))
|
||||
{
|
||||
memcpy(transientpalette.colors, data, 1024);
|
||||
if (transientpalette.paltexture) delete transientpalette.paltexture;
|
||||
transientpalette.paltexture = nullptr;
|
||||
}
|
||||
transientpalette.crc32 = index;
|
||||
palettemap[index] = 0;
|
||||
return;
|
||||
}
|
||||
palettemap[index] = FindPalette(data);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void PaletteManager::BindPalette(int index)
|
||||
{
|
||||
if (index == transientpalette.crc32)
|
||||
{
|
||||
if (transientpalette.paltexture == nullptr)
|
||||
{
|
||||
auto p = GLInterface.NewTexture();
|
||||
p->CreateTexture(256, 1, false, false);
|
||||
p->LoadTexture((uint8_t*)transientpalette.colors);
|
||||
p->SetSampler(Sampler2DNoFilter);
|
||||
transientpalette.paltexture = p;
|
||||
}
|
||||
inst->BindTexture(2, transientpalette.paltexture);
|
||||
}
|
||||
else if (palettemap[index] < palettes.Size())
|
||||
{
|
||||
auto uindex = palettemap[index];
|
||||
if (uindex != lastindex)
|
||||
{
|
||||
lastindex = uindex;
|
||||
if (palettes[uindex].paltexture == nullptr)
|
||||
{
|
||||
auto p = GLInterface.NewTexture();
|
||||
p->CreateTexture(256, 1, false, false);
|
||||
p->LoadTexture((uint8_t*)palettes[uindex].colors);
|
||||
p->SetSampler(Sampler2DNoFilter);
|
||||
palettes[uindex].paltexture = p;
|
||||
}
|
||||
inst->BindTexture(2, palettes[uindex].paltexture);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
static void polymost_setPalswap(uint32_t index)
|
||||
{
|
||||
static uint32_t lastPalswapIndex;
|
||||
|
||||
if (currentShaderProgramID != polymost1CurrentShaderProgramID)
|
||||
return;
|
||||
|
||||
lastPalswapIndex = index;
|
||||
polymost1PalswapPos.x = index * polymost1PalswapSize.x;
|
||||
polymost1PalswapPos.y = floorf(polymost1PalswapPos.x);
|
||||
polymost1PalswapPos = { polymost1PalswapPos.x - polymost1PalswapPos.y + (0.5f / PALSWAP_TEXTURE_SIZE),
|
||||
polymost1PalswapPos.y * polymost1PalswapSize.y + (0.5f / PALSWAP_TEXTURE_SIZE) };
|
||||
glUniform2f(polymost1PalswapPosLoc, polymost1PalswapPos.x, polymost1PalswapPos.y);
|
||||
}
|
||||
|
||||
static void polymost_setPalswapSize(uint32_t width, uint32_t height)
|
||||
{
|
||||
if (currentShaderProgramID != polymost1CurrentShaderProgramID)
|
||||
return;
|
||||
|
||||
polymost1PalswapSize = { width * (1.f / PALSWAP_TEXTURE_SIZE),
|
||||
height * (1.f / PALSWAP_TEXTURE_SIZE) };
|
||||
|
||||
polymost1PalswapInnerSize = { (width - 1) * (1.f / PALSWAP_TEXTURE_SIZE),
|
||||
(height - 1) * (1.f / PALSWAP_TEXTURE_SIZE) };
|
||||
|
||||
glUniform2f(polymost1PalswapSizeLoc, polymost1PalswapInnerSize.x, polymost1PalswapInnerSize.y);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -41,6 +41,12 @@ FileReader GetBaseResource(const char* fn)
|
|||
|
||||
GLInstance GLInterface;
|
||||
|
||||
GLInstance::GLInstance()
|
||||
:palmanager(this)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void GLInstance::Init()
|
||||
{
|
||||
InitBaseRes();
|
||||
|
@ -146,8 +152,12 @@ void GLInstance::Deinit()
|
|||
mSamplers = nullptr;
|
||||
if (polymostShader) delete polymostShader;
|
||||
polymostShader = nullptr;
|
||||
|
||||
if (surfaceShader) delete surfaceShader;
|
||||
surfaceShader = nullptr;
|
||||
if (vpxShader) delete vpxShader;
|
||||
vpxShader = nullptr;
|
||||
activeShader = nullptr;
|
||||
palmanager.DeleteAll();
|
||||
}
|
||||
|
||||
std::pair<size_t, BaseVertex *> GLInstance::AllocVertices(size_t num)
|
||||
|
@ -402,9 +412,6 @@ void GLInstance::SetPolymostShader()
|
|||
polymostShader->Bind();
|
||||
activeShader = polymostShader;
|
||||
}
|
||||
//GLInterface.BindTexture(1, palswapTextureID);
|
||||
//GLInterface.BindTexture(2, paletteTextureIDs[curbasepal]);
|
||||
|
||||
}
|
||||
|
||||
void GLInstance::SetSurfaceShader()
|
||||
|
@ -425,6 +432,10 @@ void GLInstance::SetVPXShader()
|
|||
}
|
||||
}
|
||||
|
||||
void GLInstance::SetPalette(int index)
|
||||
{
|
||||
palmanager.BindPalette(index);
|
||||
}
|
||||
|
||||
void PolymostRenderState::Apply(PolymostShader* shader)
|
||||
{
|
||||
|
@ -446,36 +457,3 @@ void PolymostRenderState::Apply(PolymostShader* shader)
|
|||
shader->FogColor.Set(FogColor);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
static void polymost_setPalswap(uint32_t index)
|
||||
{
|
||||
static uint32_t lastPalswapIndex;
|
||||
|
||||
if (currentShaderProgramID != polymost1CurrentShaderProgramID)
|
||||
return;
|
||||
|
||||
lastPalswapIndex = index;
|
||||
polymost1PalswapPos.x = index * polymost1PalswapSize.x;
|
||||
polymost1PalswapPos.y = floorf(polymost1PalswapPos.x);
|
||||
polymost1PalswapPos = { polymost1PalswapPos.x - polymost1PalswapPos.y + (0.5f / PALSWAP_TEXTURE_SIZE),
|
||||
polymost1PalswapPos.y * polymost1PalswapSize.y + (0.5f / PALSWAP_TEXTURE_SIZE) };
|
||||
glUniform2f(polymost1PalswapPosLoc, polymost1PalswapPos.x, polymost1PalswapPos.y);
|
||||
}
|
||||
|
||||
static void polymost_setPalswapSize(uint32_t width, uint32_t height)
|
||||
{
|
||||
if (currentShaderProgramID != polymost1CurrentShaderProgramID)
|
||||
return;
|
||||
|
||||
polymost1PalswapSize = { width * (1.f / PALSWAP_TEXTURE_SIZE),
|
||||
height * (1.f / PALSWAP_TEXTURE_SIZE) };
|
||||
|
||||
polymost1PalswapInnerSize = { (width - 1) * (1.f / PALSWAP_TEXTURE_SIZE),
|
||||
(height - 1) * (1.f / PALSWAP_TEXTURE_SIZE) };
|
||||
|
||||
glUniform2f(polymost1PalswapSizeLoc, polymost1PalswapInnerSize.x, polymost1PalswapInnerSize.y);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -14,6 +14,46 @@ class FShader;
|
|||
class PolymostShader;
|
||||
class SurfaceShader;
|
||||
class FTexture;
|
||||
class GLInstance;
|
||||
|
||||
struct PaletteData
|
||||
{
|
||||
int32_t crc32;
|
||||
PalEntry colors[256];
|
||||
FHardwareTexture* paltexture;
|
||||
};
|
||||
|
||||
class PaletteManager
|
||||
{
|
||||
// The current engine limit is 256 palettes and 256 palswaps.
|
||||
uint32_t palettemap[256] = {};
|
||||
uint32_t palswapmap[256] = {};
|
||||
uint32_t lastindex = ~0u;
|
||||
|
||||
// Keep the short lived movie palettes out of the palette list for ease of maintenance.
|
||||
// Since it is transient this doesn't need to be preserved if it changes, unlike the other palettes which need to be preserved as references for the texture management.
|
||||
PaletteData transientpalette = { -1 };
|
||||
|
||||
// All data is being stored in contiguous blocks that can be used as uniform buffers as-is.
|
||||
TArray<PaletteData> palettes;
|
||||
TArray<uint8_t> palswaps;
|
||||
GLInstance* const inst;
|
||||
|
||||
//OpenGLRenderer::GLDataBuffer* palswapBuffer = nullptr;
|
||||
|
||||
unsigned FindPalette(const uint8_t* paldata);
|
||||
|
||||
public:
|
||||
PaletteManager(GLInstance *inst_) : inst(inst_)
|
||||
{}
|
||||
~PaletteManager();
|
||||
void DeleteAll();
|
||||
void SetPalette(int index, const uint8_t *data, bool transient);
|
||||
void AddPalswap(const uint8_t* data);
|
||||
|
||||
void BindPalette(int index);
|
||||
};
|
||||
|
||||
|
||||
struct glinfo_t {
|
||||
const char* vendor;
|
||||
|
@ -128,6 +168,7 @@ class GLInstance
|
|||
unsigned TextureHandleCache[THCACHESIZE];
|
||||
int currentindex = THCACHESIZE;
|
||||
int maxTextureSize;
|
||||
PaletteManager palmanager;
|
||||
|
||||
VSMatrix matrices[NUMMATRICES];
|
||||
PolymostRenderState renderState;
|
||||
|
@ -155,6 +196,7 @@ public:
|
|||
return value;
|
||||
}
|
||||
|
||||
GLInstance();
|
||||
std::pair<size_t, BaseVertex *> AllocVertices(size_t num);
|
||||
void Draw(EDrawType type, size_t start, size_t count);
|
||||
|
||||
|
@ -203,9 +245,15 @@ public:
|
|||
void SetPolymostShader();
|
||||
void SetSurfaceShader();
|
||||
void SetVPXShader();
|
||||
void SetPalette(int palette);
|
||||
|
||||
void ReadPixels(int w, int h, uint8_t* buffer);
|
||||
|
||||
void SetPaletteData(int index, const uint8_t* data, bool transient)
|
||||
{
|
||||
palmanager.SetPalette(index, data, transient);
|
||||
}
|
||||
|
||||
|
||||
void SetPalswap(uint32_t index)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue