mirror of
https://github.com/blawar/GLideN64.git
synced 2024-07-07 03:13:49 +00:00
235 lines
6.0 KiB
C++
235 lines
6.0 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::get().init();
|
|
InitShaderCombiner();
|
|
}
|
|
|
|
void Combiner_Destroy() {
|
|
DestroyShaderCombiner();
|
|
CombinerInfo::get().destroy();
|
|
}
|
|
|
|
void CombinerInfo::init()
|
|
{
|
|
m_pCurrent = NULL;
|
|
}
|
|
|
|
void CombinerInfo::destroy()
|
|
{
|
|
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;
|
|
|
|
if (gDP.otherMode.cycleType == G_CYC_2CYCLE) {
|
|
numCycles = 2;
|
|
color.numStages = 2;
|
|
alpha.numStages = 2;
|
|
} else {
|
|
numCycles = 1;
|
|
if (combine.saRGB0 != combine.saRGB1 || combine.sbRGB0 != combine.sbRGB1 || combine.mRGB0 != combine.mRGB1 || combine.aRGB0 != combine.aRGB1 ||
|
|
combine.saA0 != combine.saA1 || combine.sbA0 != combine.sbA1 || combine.mA0 != combine.mA1 || combine.aA0 != combine.aA1)
|
|
numCycles = 2;
|
|
color.numStages = numCycles;
|
|
alpha.numStages = numCycles;
|
|
}
|
|
|
|
CombineCycle cc[2];
|
|
CombineCycle ac[2];
|
|
|
|
// Decode and expand the combine mode into a more general form
|
|
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];
|
|
|
|
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];
|
|
|
|
for (int i = 0; i < numCycles; i++) {
|
|
// Simplify each RDP combiner cycle into a combiner stage
|
|
SimplifyCycle( &cc[i], &color.stage[i] );
|
|
SimplifyCycle( &ac[i], &alpha.stage[i] );
|
|
}
|
|
|
|
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_combiners[_mux] = m_pCurrent;
|
|
}
|
|
m_bChanged = true;
|
|
gDP.changed |= CHANGED_COMBINE_COLORS;
|
|
}
|