mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Merge pull request #11319 from unknownbrackets/logicop
GPU: Apply logic op in more cases
This commit is contained in:
commit
569c073497
4 changed files with 38 additions and 22 deletions
|
@ -813,22 +813,16 @@ static inline bool blendColorSimilar(uint32_t a, uint32_t b, int margin = 25) {
|
|||
}
|
||||
|
||||
// Try to simulate some common logic ops.
|
||||
void ApplyStencilReplaceAndLogicOp(ReplaceAlphaType replaceAlphaWithStencil, GenericBlendState &blendState) {
|
||||
StencilValueType stencilType = STENCIL_VALUE_KEEP;
|
||||
if (replaceAlphaWithStencil == REPLACE_ALPHA_YES) {
|
||||
stencilType = ReplaceAlphaWithStencilType();
|
||||
}
|
||||
|
||||
// Normally, we would add src + 0, but the logic op may have us do differently.
|
||||
BlendFactor srcBlend = BlendFactor::ONE;
|
||||
BlendFactor dstBlend = BlendFactor::ZERO;
|
||||
BlendEq blendEq = BlendEq::ADD;
|
||||
|
||||
static void ApplyLogicOp(BlendFactor &srcBlend, BlendFactor &dstBlend, BlendEq &blendEq) {
|
||||
// Note: our shader solution applies logic ops BEFORE blending, not correctly after.
|
||||
// This is however fine for the most common ones, like CLEAR/NOOP/SET, etc.
|
||||
if (!gstate_c.Supports(GPU_SUPPORTS_LOGIC_OP)) {
|
||||
if (gstate.isLogicOpEnabled()) {
|
||||
switch (gstate.getLogicOp()) {
|
||||
case GE_LOGIC_CLEAR:
|
||||
srcBlend = BlendFactor::ZERO;
|
||||
dstBlend = BlendFactor::ZERO;
|
||||
blendEq = BlendEq::ADD;
|
||||
break;
|
||||
case GE_LOGIC_AND:
|
||||
case GE_LOGIC_AND_REVERSE:
|
||||
|
@ -856,6 +850,7 @@ void ApplyStencilReplaceAndLogicOp(ReplaceAlphaType replaceAlphaWithStencil, Gen
|
|||
case GE_LOGIC_NOOP:
|
||||
srcBlend = BlendFactor::ZERO;
|
||||
dstBlend = BlendFactor::ONE;
|
||||
blendEq = BlendEq::ADD;
|
||||
break;
|
||||
case GE_LOGIC_XOR:
|
||||
WARN_LOG_REPORT_ONCE(d3dLogicOpOrXor, G3D, "Unsupported XOR logic op: %x", gstate.getLogicOp());
|
||||
|
@ -870,14 +865,30 @@ void ApplyStencilReplaceAndLogicOp(ReplaceAlphaType replaceAlphaWithStencil, Gen
|
|||
WARN_LOG_REPORT_ONCE(d3dLogicOpOrReverse, G3D, "Unsupported OR REVERSE logic op: %x", gstate.getLogicOp());
|
||||
break;
|
||||
case GE_LOGIC_SET:
|
||||
srcBlend = BlendFactor::ONE;
|
||||
dstBlend = BlendFactor::ONE;
|
||||
blendEq = BlendEq::ADD;
|
||||
WARN_LOG_REPORT_ONCE(d3dLogicOpSet, G3D, "Attempted set for logic op: %x", gstate.getLogicOp());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We're not blending, but we may still want to blend for stencil.
|
||||
// Try to simulate some common logic ops.
|
||||
void ApplyStencilReplaceAndLogicOp(ReplaceAlphaType replaceAlphaWithStencil, GenericBlendState &blendState) {
|
||||
StencilValueType stencilType = STENCIL_VALUE_KEEP;
|
||||
if (replaceAlphaWithStencil == REPLACE_ALPHA_YES) {
|
||||
stencilType = ReplaceAlphaWithStencilType();
|
||||
}
|
||||
|
||||
// Normally, we would add src + 0 with blending off, but the logic op may have us do differently.
|
||||
BlendFactor srcBlend = BlendFactor::ONE;
|
||||
BlendFactor dstBlend = BlendFactor::ZERO;
|
||||
BlendEq blendEq = BlendEq::ADD;
|
||||
ApplyLogicOp(srcBlend, dstBlend, blendEq);
|
||||
|
||||
// We're not blending, but we may still want to "blend" for stencil.
|
||||
// This is only useful for INCR/DECR/INVERT. Others can write directly.
|
||||
switch (stencilType) {
|
||||
case STENCIL_VALUE_INCR_4:
|
||||
|
@ -1105,6 +1116,15 @@ void ConvertBlendState(GenericBlendState &blendState, bool allowShaderBlend) {
|
|||
#endif
|
||||
|
||||
// At this point, through all paths above, glBlendFuncA and glBlendFuncB will be set right somehow.
|
||||
BlendEq colorEq;
|
||||
if (gstate_c.Supports(GPU_SUPPORTS_BLEND_MINMAX)) {
|
||||
colorEq = eqLookup[blendFuncEq];
|
||||
} else {
|
||||
colorEq = eqLookupNoMinMax[blendFuncEq];
|
||||
}
|
||||
|
||||
// Attempt to apply the logic op, if any.
|
||||
ApplyLogicOp(glBlendFuncA, glBlendFuncB, colorEq);
|
||||
|
||||
// The stencil-to-alpha in fragment shader doesn't apply here (blending is enabled), and we shouldn't
|
||||
// do any blending in the alpha channel as that doesn't seem to happen on PSP. So, we attempt to
|
||||
|
@ -1174,11 +1194,7 @@ void ConvertBlendState(GenericBlendState &blendState, bool allowShaderBlend) {
|
|||
blendState.setFactors(glBlendFuncA, glBlendFuncB, BlendFactor::ZERO, BlendFactor::ONE);
|
||||
}
|
||||
|
||||
if (gstate_c.Supports(GPU_SUPPORTS_BLEND_MINMAX)) {
|
||||
blendState.setEquation(eqLookup[blendFuncEq], alphaEq);
|
||||
} else {
|
||||
blendState.setEquation(eqLookupNoMinMax[blendFuncEq], alphaEq);
|
||||
}
|
||||
blendState.setEquation(colorEq, alphaEq);
|
||||
}
|
||||
|
||||
static void ConvertStencilFunc5551(GenericStencilFuncState &state) {
|
||||
|
|
|
@ -972,7 +972,7 @@ inline void DrawSinglePixel(const DrawingCoords &p, u16 z, u8 fog, const Vec4<in
|
|||
#endif
|
||||
}
|
||||
|
||||
// TODO: Is alpha blending still performed if logic ops are enabled?
|
||||
// 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);
|
||||
|
@ -980,9 +980,8 @@ inline void DrawSinglePixel(const DrawingCoords &p, u16 z, u8 fog, const Vec4<in
|
|||
|
||||
if (clearMode) {
|
||||
new_color = (new_color & ~gstate.getClearModeColorMask()) | (old_color & gstate.getClearModeColorMask());
|
||||
} else {
|
||||
new_color = (new_color & ~gstate.getColorMask()) | (old_color & gstate.getColorMask());
|
||||
}
|
||||
new_color = (new_color & ~gstate.getColorMask()) | (old_color & gstate.getColorMask());
|
||||
|
||||
// TODO: Dither before or inside SetPixelColor
|
||||
SetPixelColor(p.x, p.y, new_color);
|
||||
|
@ -1554,6 +1553,9 @@ void ClearRectangle(const VertexData &v0, const VertexData &v1)
|
|||
break;
|
||||
}
|
||||
|
||||
// The pixel write masks are respected in clear mode.
|
||||
keepOldMask &= ~gstate.getColorMask();
|
||||
|
||||
if (keepOldMask == 0) {
|
||||
ScreenCoords pprime(minX, minY, 0);
|
||||
const int stride = gstate.FrameBufStride();
|
||||
|
|
|
@ -49,7 +49,6 @@ protected:
|
|||
STOPPED,
|
||||
};
|
||||
|
||||
GraphicsContext *gfx_;
|
||||
volatile RenderThreadState threadState_ = RenderThreadState::IDLE;
|
||||
};
|
||||
|
||||
|
|
|
@ -53,6 +53,5 @@ protected:
|
|||
HWND hWnd;
|
||||
HDC hDC;
|
||||
HGLRC hRC;
|
||||
GraphicsContext *gfx_;
|
||||
volatile RenderThreadState threadState_ = RenderThreadState::IDLE;
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue