Skip to content

Commit

Permalink
SoftGPU: Preserve stencil inside logic op func.
Browse files Browse the repository at this point in the history
Cleaning things up to make it easier to translate.
  • Loading branch information
unknownbrackets committed Sep 10, 2018
1 parent 772ed30 commit 8cdead9
Showing 1 changed file with 22 additions and 25 deletions.
47 changes: 22 additions & 25 deletions GPU/Software/Rasterizer.cpp
Expand Up @@ -537,71 +537,71 @@ static inline u8 ApplyStencilOp(int op, u8 old_stencil) {
return old_stencil;
}

static inline u32 ApplyLogicOp(GELogicOp op, u32 old_color, u32 new_color)
{
static inline u32 ApplyLogicOp(GELogicOp op, u32 old_color, u32 new_color) {
// All of the operations here intentionally preserve alpha/stencil.
switch (op) {
case GE_LOGIC_CLEAR:
new_color = 0;
new_color &= 0xFF000000;
break;

case GE_LOGIC_AND:
new_color = new_color & old_color;
new_color = new_color & (old_color | 0xFF000000);
break;

case GE_LOGIC_AND_REVERSE:
new_color = new_color & ~old_color;
new_color = new_color & (~old_color | 0xFF000000);
break;

case GE_LOGIC_COPY:
//new_color = new_color;
// No change to new_color.
break;

case GE_LOGIC_AND_INVERTED:
new_color = ~new_color & old_color;
new_color = (~new_color & (old_color & 0x00FFFFFF)) | (new_color & 0xFF000000);
break;

case GE_LOGIC_NOOP:
new_color = old_color;
new_color = (old_color & 0x00FFFFFF) | (new_color & 0xFF000000);
break;

case GE_LOGIC_XOR:
new_color = new_color ^ old_color;
new_color = new_color ^ (old_color & 0x00FFFFFF);
break;

case GE_LOGIC_OR:
new_color = new_color | old_color;
new_color = new_color | (old_color & 0x00FFFFFF);
break;

case GE_LOGIC_NOR:
new_color = ~(new_color | old_color);
new_color = (~(new_color | old_color) & 0x00FFFFFF) | (new_color & 0xFF000000);
break;

case GE_LOGIC_EQUIV:
new_color = ~(new_color ^ old_color);
new_color = (~(new_color ^ old_color) & 0x00FFFFFF) | (new_color & 0xFF000000);
break;

case GE_LOGIC_INVERTED:
new_color = ~old_color;
new_color = (~old_color & 0x00FFFFFF) | (new_color & 0xFF000000);
break;

case GE_LOGIC_OR_REVERSE:
new_color = new_color | ~old_color;
new_color = new_color | (~old_color & 0x00FFFFFF);
break;

case GE_LOGIC_COPY_INVERTED:
new_color = ~new_color;
new_color = (~new_color & 0x00FFFFFF) | (new_color & 0xFF000000);
break;

case GE_LOGIC_OR_INVERTED:
new_color = ~new_color | old_color;
new_color = ((~new_color | old_color) & 0x00FFFFFF) | (new_color & 0xFF000000);
break;

case GE_LOGIC_NAND:
new_color = ~(new_color & old_color);
new_color = (~(new_color & old_color) & 0x00FFFFFF) | (new_color & 0xFF000000);
break;

case GE_LOGIC_SET:
new_color = 0xFFFFFFFF;
new_color |= 0x00FFFFFF;
break;
}

Expand Down Expand Up @@ -895,8 +895,7 @@ static inline Vec3<int> AlphaBlendingResult(const Vec4<int> &source, const Vec4<
template <bool clearMode>
inline void DrawSinglePixel(const DrawingCoords &p, u16 z, u8 fog, const Vec4<int> &color_in) {
Vec4<int> prim_color = color_in;
// Depth range test
// TODO: Clear mode?
// Depth range test - applied in clear mode, if not through mode.
if (!gstate.isModeThrough())
if (z < gstate.getDepthRangeMin() || z > gstate.getDepthRangeMax())
return;
Expand All @@ -905,14 +904,12 @@ inline void DrawSinglePixel(const DrawingCoords &p, u16 z, u8 fog, const Vec4<in
if (!ColorTestPassed(prim_color.rgb()))
return;

// TODO: Does a need to be clamped?
if (gstate.isAlphaTestEnabled() && !clearMode)
if (!AlphaTestPassed(prim_color.a()))
return;

// In clear mode, it uses the alpha color as stencil.
u8 stencil = clearMode ? prim_color.a() : GetPixelStencil(p.x, p.y);
// TODO: Is it safe to ignore gstate.isDepthTestEnabled() when clear mode is enabled? Probably yes
if (!clearMode && (gstate.isStencilTestEnabled() || gstate.isDepthTestEnabled())) {
if (gstate.isStencilTestEnabled() && !StencilTestPassed(stencil)) {
stencil = ApplyStencilOp(gstate.getStencilOpSFail(), stencil);
Expand Down Expand Up @@ -959,7 +956,7 @@ inline void DrawSinglePixel(const DrawingCoords &p, u16 z, u8 fog, const Vec4<in

if (gstate.isAlphaBlendEnabled() && !clearMode) {
const Vec4<int> dst = Vec4<int>::FromRGBA(old_color);
// ToRGBA() always automatically clamps.
// ToRGB() always automatically clamps.
new_color = AlphaBlendingResult(prim_color, dst).ToRGB();
new_color |= stencil << 24;
} else {
Expand All @@ -973,8 +970,8 @@ inline void DrawSinglePixel(const DrawingCoords &p, u16 z, u8 fog, const Vec4<in

// Logic ops are applied after blending (if blending is enabled.)
if (gstate.isLogicOpEnabled() && !clearMode) {
// Logic ops don't affect stencil.
new_color = (stencil << 24) | (ApplyLogicOp(gstate.getLogicOp(), old_color, new_color) & 0x00FFFFFF);
// Logic ops don't affect stencil, which happens inside ApplyLogicOp.
new_color = ApplyLogicOp(gstate.getLogicOp(), old_color, new_color);
}

if (clearMode) {
Expand Down

0 comments on commit 8cdead9

Please sign in to comment.