1
0
mirror of https://github.com/blawar/GLideN64.git synced 2024-07-07 03:13:49 +00:00
GLideN64/Combiner.cpp
Sergey Lipskiy f6c2437e18 Remove PolygonStipple related code and its control from the GUI.
Add GUI control for hardware lighting instead.
2015-05-13 10:10:33 +06:00

356 lines
8.1 KiB
C++

#ifndef __LINUX__
# include <windows.h>
#else
# include "winlnxdefs.h"
#endif // __LINUX__
#include "OpenGL.h"
#include "Combiner.h"
#include "GLSLCombiner.h"
#include "Debug.h"
#include "gDP.h"
CombinerInfo combiner;
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
};
static int CCEncodeA[] =
{
0, 1, 2, 3, 4, 5, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 7, 15, 15, 6, 15
};
static int CCEncodeB[] =
{
0, 1, 2, 3, 4, 5, 6, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 7, 15, 15, 15
};
static int CCEncodeC[] =
{
0, 1, 2, 3, 4, 5, 31, 6, 7, 8, 9, 10, 11, 12, 13, 14, 31, 31, 15, 31, 31
};
static int CCEncodeD[] =
{
0, 1, 2, 3, 4, 5, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 6, 15
};
static DWORD64 ACEncodeA[] =
{
7, 7, 7, 7, 7, 7, 7, 7, 0, 1, 2, 3, 4, 5, 7, 7, 7, 7, 7, 6, 7
};
static DWORD64 ACEncodeB[] =
{
7, 7, 7, 7, 7, 7, 7, 7, 0, 1, 2, 3, 4, 5, 7, 7, 7, 7, 7, 6, 7
};
static DWORD64 ACEncodeC[] =
{
7, 7, 7, 7, 7, 7, 7, 7, 0, 1, 2, 3, 4, 5, 7, 6, 7, 7, 7, 7, 7
};
static DWORD64 ACEncodeD[] =
{
7, 7, 7, 7, 7, 7, 7, 7, 0, 1, 2, 3, 4, 5, 7, 7, 7, 7, 7, 6, 7
};
void Combiner_Init()
{
InitGLSLCombiner();
combiner.root = NULL;
combiner.current = NULL;
}
void Combiner_UpdateCombineColors()
{
combiner.current->compiled->UpdateColors();
gDP.changed &= ~CHANGED_COMBINE_COLORS;
}
void Combiner_UpdateCombineFBInfo()
{
combiner.current->compiled->UpdateFBInfo();
gDP.changed &= ~CHANGED_FB_TEXTURE;
}
void Combiner_UpdateCombineDepthInfo()
{
if (combiner.current != NULL)
combiner.current->compiled->UpdateDepthInfo();
}
void Combiner_UpdateAlphaTestInfo()
{
if (combiner.current != NULL)
combiner.current->compiled->UpdateAlphaTestInfo();
}
void Combiner_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;
}
}
CachedCombiner *Combiner_Compile( u64 mux )
{
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;
color.numStages = 1;
alpha.numStages = 1;
}
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
Combiner_SimplifyCycle( &cc[i], &color.stage[i] );
Combiner_SimplifyCycle( &ac[i], &alpha.stage[i] );
}
CachedCombiner *cached = (CachedCombiner*)malloc( sizeof( CachedCombiner ) );
cached->combine.mux = combine.mux;
cached->left = NULL;
cached->right = NULL;
cached->compiled = new GLSLCombiner( &color, &alpha );
return cached;
}
void Combiner_DeleteCombiner( CachedCombiner *combiner )
{
if (combiner->left) Combiner_DeleteCombiner( combiner->left );
if (combiner->right) Combiner_DeleteCombiner( combiner->right );
delete combiner->compiled;
free( combiner );
}
void Combiner_Destroy()
{
DestroyGLSLCombiner();
if (combiner.root)
{
Combiner_DeleteCombiner( combiner.root );
combiner.root = NULL;
}
for (int i = 0; i < OGL.maxTextureUnits; i++)
{
glActiveTexture( GL_TEXTURE0 + i );
glDisable( GL_TEXTURE_2D );
}
}
DWORD64 Combiner_EncodeCombineMode( WORD saRGB0, WORD sbRGB0, WORD mRGB0, WORD aRGB0,
WORD saA0, WORD sbA0, WORD mA0, WORD aA0,
WORD saRGB1, WORD sbRGB1, WORD mRGB1, WORD aRGB1,
WORD saA1, WORD sbA1, WORD mA1, WORD aA1 )
{
return (((DWORD64)CCEncodeA[saRGB0] << 52) | ((DWORD64)CCEncodeB[sbRGB0] << 28) | ((DWORD64)CCEncodeC[mRGB0] << 47) | ((DWORD64)CCEncodeD[aRGB0] << 15) |
((DWORD64)ACEncodeA[saA0] << 44) | ((DWORD64)ACEncodeB[sbA0] << 12) | ((DWORD64)ACEncodeC[mA0] << 41) | ((DWORD64)ACEncodeD[aA0] << 9) |
((DWORD64)CCEncodeA[saRGB1] << 37) | ((DWORD64)CCEncodeB[sbRGB1] << 24) | ((DWORD64)CCEncodeC[mRGB1] ) | ((DWORD64)CCEncodeD[aRGB1] << 6) |
((DWORD64)ACEncodeA[saA1] << 18) | ((DWORD64)ACEncodeB[sbA1] << 3) | ((DWORD64)ACEncodeC[mA1] << 18) | ((DWORD64)ACEncodeD[aA1] ));
}
void Combiner_SelectCombine( u64 mux )
{
CachedCombiner *current = combiner.root;
CachedCombiner *parent = current;
while (current)
{
parent = current;
if (mux == current->combine.mux)
break;
else if (mux < current->combine.mux)
current = current->left;
else
current = current->right;
}
if (current == NULL)
{
current = Combiner_Compile( mux );
if (parent == NULL)
combiner.root = current;
else if (parent->combine.mux > current->combine.mux)
parent->left = current;
else
parent->right = current;
}
combiner.current = current;
gDP.changed |= CHANGED_COMBINE_COLORS;
}
void Combiner_SetCombineStates()
{
combiner.current->compiled->Set();
}
void Combiner_SetCombine( u64 mux )
{
Combiner_SelectCombine( mux );
Combiner_SetCombineStates();
}