mirror of
https://github.com/blawar/GLideN64.git
synced 2024-07-04 10:03:36 +00:00
296 lines
7.5 KiB
C++
296 lines
7.5 KiB
C++
#include "OpenGL.h"
|
|
#include "Combiner.h"
|
|
#include "GLSLCombiner.h"
|
|
#include "Debug.h"
|
|
#include "gDP.h"
|
|
|
|
static int saRGBExpanded[] =
|
|
{
|
|
COMBINED, TEXEL0, TEXEL1, PRIMITIVE,
|
|
SHADE, ENVIRONMENT, ONE, NOISE,
|
|
ZERO, ZERO, ZERO, ZERO,
|
|
ZERO, ZERO, ZERO, ZERO
|
|
};
|
|
|
|
static int sbRGBExpanded[] =
|
|
{
|
|
COMBINED, TEXEL0, TEXEL1, PRIMITIVE,
|
|
SHADE, ENVIRONMENT, CENTER, K4,
|
|
ZERO, ZERO, ZERO, ZERO,
|
|
ZERO, ZERO, ZERO, ZERO
|
|
};
|
|
|
|
static int mRGBExpanded[] =
|
|
{
|
|
COMBINED, TEXEL0, TEXEL1, PRIMITIVE,
|
|
SHADE, ENVIRONMENT, SCALE, COMBINED_ALPHA,
|
|
TEXEL0_ALPHA, TEXEL1_ALPHA, PRIMITIVE_ALPHA, SHADE_ALPHA,
|
|
ENV_ALPHA, LOD_FRACTION, PRIM_LOD_FRAC, K5,
|
|
ZERO, ZERO, ZERO, ZERO,
|
|
ZERO, ZERO, ZERO, ZERO,
|
|
ZERO, ZERO, ZERO, ZERO,
|
|
ZERO, ZERO, ZERO, ZERO
|
|
};
|
|
|
|
static int aRGBExpanded[] =
|
|
{
|
|
COMBINED, TEXEL0, TEXEL1, PRIMITIVE,
|
|
SHADE, ENVIRONMENT, ONE, ZERO
|
|
};
|
|
|
|
static int saAExpanded[] =
|
|
{
|
|
COMBINED, TEXEL0_ALPHA, TEXEL1_ALPHA, PRIMITIVE_ALPHA,
|
|
SHADE_ALPHA, ENV_ALPHA, ONE, ZERO
|
|
};
|
|
|
|
static int sbAExpanded[] =
|
|
{
|
|
COMBINED, TEXEL0_ALPHA, TEXEL1_ALPHA, PRIMITIVE_ALPHA,
|
|
SHADE_ALPHA, ENV_ALPHA, ONE, ZERO
|
|
};
|
|
|
|
static int mAExpanded[] =
|
|
{
|
|
LOD_FRACTION, TEXEL0_ALPHA, TEXEL1_ALPHA, PRIMITIVE_ALPHA,
|
|
SHADE_ALPHA, ENV_ALPHA, PRIM_LOD_FRAC, ZERO,
|
|
};
|
|
|
|
static int aAExpanded[] =
|
|
{
|
|
COMBINED, TEXEL0_ALPHA, TEXEL1_ALPHA, PRIMITIVE_ALPHA,
|
|
SHADE_ALPHA, ENV_ALPHA, ONE, ZERO
|
|
};
|
|
|
|
void Combiner_Init() {
|
|
CombinerInfo & cmbInfo = CombinerInfo::get();
|
|
cmbInfo.init();
|
|
InitShaderCombiner();
|
|
gDP.otherMode.cycleType = G_CYC_1CYCLE;
|
|
cmbInfo.setCombine(EncodeCombineMode(0, 0, 0, TEXEL0, 0, 0, 0, TEXEL0, 0, 0, 0, TEXEL0, 0, 0, 0, TEXEL0));
|
|
cmbInfo.setCombine(EncodeCombineMode(0, 0, 0, TEXEL0, 0, 0, 0, 1, 0, 0, 0, TEXEL0, 0, 0, 0, 1));
|
|
}
|
|
|
|
void Combiner_Destroy() {
|
|
DestroyShaderCombiner();
|
|
CombinerInfo::get().destroy();
|
|
}
|
|
|
|
CombinerInfo & CombinerInfo::get()
|
|
{
|
|
static CombinerInfo info;
|
|
return info;
|
|
}
|
|
|
|
void CombinerInfo::init()
|
|
{
|
|
m_pCurrent = NULL;
|
|
m_pUniformBlock = new UniformBlock;
|
|
}
|
|
|
|
void CombinerInfo::destroy()
|
|
{
|
|
delete m_pUniformBlock;
|
|
m_pUniformBlock = NULL;
|
|
m_pCurrent = NULL;
|
|
for (Combiners::iterator cur = m_combiners.begin(); cur != m_combiners.end(); ++cur)
|
|
delete cur->second;
|
|
m_combiners.clear();
|
|
}
|
|
|
|
static
|
|
void SimplifyCycle( CombineCycle *cc, CombinerStage *stage )
|
|
{
|
|
// Load the first operand
|
|
stage->op[0].op = LOAD;
|
|
stage->op[0].param1 = cc->sa;
|
|
stage->numOps = 1;
|
|
|
|
// If we're just subtracting zero, skip it
|
|
if (cc->sb != ZERO) {
|
|
// Subtracting a number from itself is zero
|
|
if (cc->sb == stage->op[0].param1)
|
|
stage->op[0].param1 = ZERO;
|
|
else {
|
|
stage->op[1].op = SUB;
|
|
stage->op[1].param1 = cc->sb;
|
|
stage->numOps++;
|
|
}
|
|
}
|
|
|
|
// If we either subtracted, or didn't load a zero
|
|
if ((stage->numOps > 1) || (stage->op[0].param1 != ZERO)) {
|
|
// Multiplying by zero is zero
|
|
if (cc->m == ZERO) {
|
|
stage->numOps = 1;
|
|
stage->op[0].op = LOAD;
|
|
stage->op[0].param1 = ZERO;
|
|
} else {
|
|
// Multiplying by one, so just do a load
|
|
if ((stage->numOps == 1) && (stage->op[0].param1 == ONE))
|
|
stage->op[0].param1 = cc->m;
|
|
else {
|
|
stage->op[stage->numOps].op = MUL;
|
|
stage->op[stage->numOps].param1 = cc->m;
|
|
stage->numOps++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Don't bother adding zero
|
|
if (cc->a != ZERO) {
|
|
// If all we have so far is zero, then load this instead
|
|
if ((stage->numOps == 1) && (stage->op[0].param1 == ZERO))
|
|
stage->op[0].param1 = cc->a;
|
|
else {
|
|
stage->op[stage->numOps].op = ADD;
|
|
stage->op[stage->numOps].param1 = cc->a;
|
|
stage->numOps++;
|
|
}
|
|
}
|
|
|
|
// Handle interpolation
|
|
if ((stage->numOps == 4) && (stage->op[1].param1 == stage->op[3].param1)) {
|
|
stage->numOps = 1;
|
|
stage->op[0].op = INTER;
|
|
stage->op[0].param2 = stage->op[1].param1;
|
|
stage->op[0].param3 = stage->op[2].param1;
|
|
}
|
|
}
|
|
|
|
ShaderCombiner * CombinerInfo::_compile(u64 mux) const
|
|
{
|
|
gDPCombine combine;
|
|
|
|
combine.mux = mux;
|
|
|
|
int numCycles;
|
|
|
|
Combiner color, alpha;
|
|
|
|
numCycles = gDP.otherMode.cycleType + 1;
|
|
color.numStages = numCycles;
|
|
alpha.numStages = numCycles;
|
|
|
|
CombineCycle cc[2];
|
|
CombineCycle ac[2];
|
|
|
|
// Decode and expand the combine mode into a more general form
|
|
cc[1].sa = saRGBExpanded[combine.saRGB1];
|
|
cc[1].sb = sbRGBExpanded[combine.sbRGB1];
|
|
cc[1].m = mRGBExpanded[combine.mRGB1];
|
|
cc[1].a = aRGBExpanded[combine.aRGB1];
|
|
ac[1].sa = saAExpanded[combine.saA1];
|
|
ac[1].sb = sbAExpanded[combine.sbA1];
|
|
ac[1].m = mAExpanded[combine.mA1];
|
|
ac[1].a = aAExpanded[combine.aA1];
|
|
|
|
// Simplify each RDP combiner cycle into a combiner stage
|
|
if (gDP.otherMode.cycleType == G_CYC_1CYCLE) {
|
|
SimplifyCycle(&cc[1], &color.stage[0]);
|
|
SimplifyCycle(&ac[1], &alpha.stage[0]);
|
|
}
|
|
else {
|
|
cc[0].sa = saRGBExpanded[combine.saRGB0];
|
|
cc[0].sb = sbRGBExpanded[combine.sbRGB0];
|
|
cc[0].m = mRGBExpanded[combine.mRGB0];
|
|
cc[0].a = aRGBExpanded[combine.aRGB0];
|
|
ac[0].sa = saAExpanded[combine.saA0];
|
|
ac[0].sb = sbAExpanded[combine.sbA0];
|
|
ac[0].m = mAExpanded[combine.mA0];
|
|
ac[0].a = aAExpanded[combine.aA0];
|
|
|
|
SimplifyCycle(&cc[0], &color.stage[0]);
|
|
SimplifyCycle(&ac[0], &alpha.stage[0]);
|
|
SimplifyCycle(&cc[1], &color.stage[1]);
|
|
SimplifyCycle(&ac[1], &alpha.stage[1]);
|
|
}
|
|
|
|
return new ShaderCombiner( color, alpha, combine );
|
|
}
|
|
|
|
void CombinerInfo::update()
|
|
{
|
|
// TODO: find, why gDP.changed & CHANGED_COMBINE not always works (e.g. Mario Tennis).
|
|
// if (gDP.changed & CHANGED_COMBINE) {
|
|
if (gDP.otherMode.cycleType == G_CYC_COPY)
|
|
setCombine(EncodeCombineMode(0, 0, 0, TEXEL0, 0, 0, 0, TEXEL0, 0, 0, 0, TEXEL0, 0, 0, 0, TEXEL0));
|
|
else if (gDP.otherMode.cycleType == G_CYC_FILL)
|
|
setCombine(EncodeCombineMode(0, 0, 0, SHADE, 0, 0, 0, SHADE, 0, 0, 0, SHADE, 0, 0, 0, SHADE));
|
|
else
|
|
setCombine(gDP.combine.mux);
|
|
gDP.changed &= ~CHANGED_COMBINE;
|
|
// }
|
|
}
|
|
|
|
void CombinerInfo::setCombine(u64 _mux )
|
|
{
|
|
if (m_pCurrent != NULL && m_pCurrent->getMux() == _mux) {
|
|
m_bChanged = false;
|
|
m_pCurrent->update(false);
|
|
return;
|
|
}
|
|
Combiners::const_iterator iter = m_combiners.find(_mux);
|
|
if (iter != m_combiners.end()) {
|
|
m_pCurrent = iter->second;
|
|
m_pCurrent->update(false);
|
|
} else {
|
|
m_pCurrent = _compile(_mux);
|
|
m_pCurrent->update(true);
|
|
m_pUniformBlock->bindWithShaderCombiner(m_pCurrent);
|
|
m_combiners[_mux] = m_pCurrent;
|
|
}
|
|
m_bChanged = true;
|
|
}
|
|
|
|
void CombinerInfo::updatePrimColor()
|
|
{
|
|
if (m_pUniformBlock != NULL)
|
|
m_pUniformBlock->setColorData(UniformBlock::cuPrimColor, sizeof(f32)* 5, &gDP.primColor.r);
|
|
}
|
|
|
|
void CombinerInfo::updateEnvColor()
|
|
{
|
|
if (m_pUniformBlock != NULL)
|
|
m_pUniformBlock->setColorData(UniformBlock::cuEnvColor, sizeof(f32)* 4, &gDP.envColor.r);
|
|
}
|
|
|
|
void CombinerInfo::updateFogColor()
|
|
{
|
|
if (m_pUniformBlock != NULL)
|
|
m_pUniformBlock->setColorData(UniformBlock::cuFogColor, sizeof(f32)* 4, &gDP.fogColor.r);
|
|
}
|
|
|
|
void CombinerInfo::updateBlendColor()
|
|
{
|
|
if (m_pUniformBlock != NULL)
|
|
m_pUniformBlock->setColorData(UniformBlock::cuBlendColor, sizeof(f32)* 4, &gDP.blendColor.r);
|
|
}
|
|
|
|
void CombinerInfo::updateKeyColor()
|
|
{
|
|
if (m_pUniformBlock != NULL)
|
|
m_pUniformBlock->setColorData(UniformBlock::cuCenterColor, sizeof(f32)* 8, &gDP.key.center.r);
|
|
}
|
|
|
|
void CombinerInfo::updateConvertColor()
|
|
{
|
|
if (m_pUniformBlock == NULL)
|
|
return;
|
|
f32 convert[2] = { gDP.convert.k4*0.0039215689f, gDP.convert.k5*0.0039215689f };
|
|
m_pUniformBlock->setColorData(UniformBlock::cuK4, sizeof(convert), convert);
|
|
}
|
|
|
|
void CombinerInfo::updateTextureParameters()
|
|
{
|
|
if (m_pUniformBlock != NULL)
|
|
m_pUniformBlock->updateTextureParameters();
|
|
}
|
|
|
|
void CombinerInfo::updateLightParameters()
|
|
{
|
|
if (m_pUniformBlock != NULL)
|
|
m_pUniformBlock->updateLightParameters();
|
|
gSP.changed &= ~CHANGED_LIGHT;
|
|
}
|