Permalink
Browse files

GPU: When rendering the 3D layer, prioritize color blending over the …

…window color effect flag.

Fixes color blending in the dialogue boxes of Front Mission.
(Regression from r5285.)
  • Loading branch information...
1 parent a80fa6d commit e6b352c73ade0d7e7277ad102c9a5e7905c4924a @rogerman rogerman committed Dec 15, 2016
Showing with 87 additions and 99 deletions.
  1. +87 −99 desmume/src/GPU.cpp
View
@@ -1659,63 +1659,56 @@ FORCEINLINE void GPUEngineBase::_RenderPixel(GPUEngineCompositorInfo &compInfo,
return;
}
- ColorEffect selectedEffect = ColorEffect_Disable;
TBlendTable *selectedBlendTable = compInfo.renderState.blendTable555;
u8 blendEVA = compInfo.renderState.blendEVA;
u8 blendEVB = compInfo.renderState.blendEVB;
- if (enableColorEffect)
+ const bool dstEffectEnable = (dstLayerID != compInfo.renderState.selectedLayerID) && compInfo.renderState.dstBlendEnable[dstLayerID];
+ bool forceBlendEffect = false;
+
+ if (ISSRCLAYEROBJ && enableColorEffect)
{
- const bool dstEffectEnable = (dstLayerID != compInfo.renderState.selectedLayerID) && compInfo.renderState.dstBlendEnable[dstLayerID];
-
- // Select the color effect based on the BLDCNT target flags.
- bool forceBlendEffect = false;
-
- if (ISSRCLAYEROBJ)
+ //translucent-capable OBJ are forcing the function to blend when the second target is satisfied
+ const OBJMode objMode = (OBJMode)this->_sprType[compInfo.target.xNative];
+ const bool isObjTranslucentType = (objMode == OBJMode_Transparent) || (objMode == OBJMode_Bitmap);
+ if (isObjTranslucentType && dstEffectEnable)
{
- //translucent-capable OBJ are forcing the function to blend when the second target is satisfied
- const OBJMode objMode = (OBJMode)this->_sprType[compInfo.target.xNative];
- const bool isObjTranslucentType = (objMode == OBJMode_Transparent) || (objMode == OBJMode_Bitmap);
- if (isObjTranslucentType && dstEffectEnable)
+ //obj without fine-grained alpha are using EVA/EVB for blending. this is signified by receiving 0xFF in the alpha
+ //it's tested by the spriteblend demo and the glory of heracles title screen
+ if (srcAlpha != 0xFF)
{
- //obj without fine-grained alpha are using EVA/EVB for blending. this is signified by receiving 0xFF in the alpha
- //it's tested by the spriteblend demo and the glory of heracles title screen
- if (srcAlpha != 0xFF)
- {
- blendEVA = srcAlpha;
- blendEVB = 16 - srcAlpha;
- selectedBlendTable = &GPUEngineBase::_blendTable555[blendEVA][blendEVB];
- }
-
- forceBlendEffect = true;
+ blendEVA = srcAlpha;
+ blendEVB = 16 - srcAlpha;
+ selectedBlendTable = &GPUEngineBase::_blendTable555[blendEVA][blendEVB];
}
+
+ forceBlendEffect = true;
}
-
- if (forceBlendEffect)
- {
- selectedEffect = ColorEffect_Blend;
- }
- else if (compInfo.renderState.srcBlendEnable[compInfo.renderState.selectedLayerID])
+ }
+
+ ColorEffect selectedEffect = (forceBlendEffect) ? ColorEffect_Blend : ColorEffect_Disable;
+
+ // If we're not forcing blending, then select the color effect based on the BLDCNT target flags.
+ if (!forceBlendEffect && enableColorEffect && compInfo.renderState.srcBlendEnable[compInfo.renderState.selectedLayerID])
+ {
+ switch (compInfo.renderState.colorEffect)
{
- switch (compInfo.renderState.colorEffect)
+ // For the Blend effect, both first and second target flags must be checked.
+ case ColorEffect_Blend:
{
- // For the Blend effect, both first and second target flags must be checked.
- case ColorEffect_Blend:
- {
- if (dstEffectEnable) selectedEffect = compInfo.renderState.colorEffect;
- break;
- }
-
- // For the Increase/Decrease Brightness effects, only the first target flag needs to be checked.
- // Test case: Bomberman Land Touch! dialog boxes will render too dark without this check.
- case ColorEffect_IncreaseBrightness:
- case ColorEffect_DecreaseBrightness:
- selectedEffect = compInfo.renderState.colorEffect;
- break;
-
- default:
- break;
+ if (dstEffectEnable) selectedEffect = compInfo.renderState.colorEffect;
+ break;
}
+
+ // For the Increase/Decrease Brightness effects, only the first target flag needs to be checked.
+ // Test case: Bomberman Land Touch! dialog boxes will render too dark without this check.
+ case ColorEffect_IncreaseBrightness:
+ case ColorEffect_DecreaseBrightness:
+ selectedEffect = compInfo.renderState.colorEffect;
+ break;
+
+ default:
+ break;
}
}
@@ -1923,7 +1916,7 @@ FORCEINLINE void GPUEngineBase::_RenderPixel16_SSE2(GPUEngineCompositorInfo &com
if (ISSRCLAYEROBJ)
{
const __m128i objMode_vec128 = _mm_loadu_si128((__m128i *)(this->_sprType + compInfo.target.xNative));
- const __m128i isObjTranslucentMask = _mm_and_si128( dstEffectEnableMask, _mm_or_si128(_mm_cmpeq_epi8(objMode_vec128, _mm_set1_epi8(OBJMode_Transparent)), _mm_cmpeq_epi8(objMode_vec128, _mm_set1_epi8(OBJMode_Bitmap))) );
+ const __m128i isObjTranslucentMask = _mm_and_si128( _mm_and_si128(enableColorEffectMask, dstEffectEnableMask), _mm_or_si128(_mm_cmpeq_epi8(objMode_vec128, _mm_set1_epi8(OBJMode_Transparent)), _mm_cmpeq_epi8(objMode_vec128, _mm_set1_epi8(OBJMode_Bitmap))) );
forceBlendEffectMask = isObjTranslucentMask;
const __m128i srcAlphaMask = _mm_andnot_si128(_mm_cmpeq_epi8(srcAlpha, _mm_set1_epi8(0xFF)), isObjTranslucentMask);
@@ -2052,45 +2045,40 @@ FORCEINLINE void GPUEngineBase::_RenderPixel3D(GPUEngineCompositorInfo &compInfo
u16 &dstColor16 = *compInfo.target.lineColor16;
FragmentColor &dstColor32 = *compInfo.target.lineColor32;
u8 &dstLayerID = *compInfo.target.lineLayerID;
- ColorEffect selectedEffect = ColorEffect_Disable;
- if (enableColorEffect)
+ const bool dstEffectEnable = (dstLayerID != GPULayerID_BG0) && compInfo.renderState.dstBlendEnable[dstLayerID];
+
+ // 3D rendering has a special override: If the destination pixel is set to blend, then always blend.
+ // Test case: When starting a stage in Super Princess Peach, the screen will be solid black unless
+ // blending is forced here.
+ //
+ // This behavior must take priority over checking for the window color effect enable flag.
+ // Test case: Dialogue boxes in Front Mission will be rendered with blending disabled unless
+ // blend forcing takes priority.
+ bool forceBlendEffect = dstEffectEnable;
+ ColorEffect selectedEffect = (forceBlendEffect) ? ColorEffect_Blend : ColorEffect_Disable;
+
+ // If we're not forcing blending, then select the color effect based on the BLDCNT target flags.
+ if (!forceBlendEffect && enableColorEffect && compInfo.renderState.srcBlendEnable[GPULayerID_BG0])
{
- const bool dstEffectEnable = (dstLayerID != GPULayerID_BG0) && compInfo.renderState.dstBlendEnable[dstLayerID];
-
- // Select the color effect based on the BLDCNT target flags.
- bool forceBlendEffect = false;
-
- // 3D rendering has a special override: If the destination pixel is set to blend, then always blend.
- // Test case: When starting a stage in Super Princess Peach, the screen will be solid black unless
- // blending is forced here.
- forceBlendEffect = dstEffectEnable;
-
- if (forceBlendEffect)
+ switch (compInfo.renderState.colorEffect)
{
- selectedEffect = ColorEffect_Blend;
- }
- else if (compInfo.renderState.srcBlendEnable[GPULayerID_BG0])
- {
- switch (compInfo.renderState.colorEffect)
+ // For the Blend effect, both first and second target flags must be checked.
+ case ColorEffect_Blend:
{
- // For the Blend effect, both first and second target flags must be checked.
- case ColorEffect_Blend:
- {
- if (dstEffectEnable) selectedEffect = compInfo.renderState.colorEffect;
- break;
- }
-
- // For the Increase/Decrease Brightness effects, only the first target flag needs to be checked.
- // Test case: Bomberman Land Touch! dialog boxes will render too dark without this check.
- case ColorEffect_IncreaseBrightness:
- case ColorEffect_DecreaseBrightness:
- selectedEffect = compInfo.renderState.colorEffect;
- break;
-
- default:
- break;
+ if (dstEffectEnable) selectedEffect = compInfo.renderState.colorEffect;
+ break;
}
+
+ // For the Increase/Decrease Brightness effects, only the first target flag needs to be checked.
+ // Test case: Bomberman Land Touch! dialog boxes will render too dark without this check.
+ case ColorEffect_IncreaseBrightness:
+ case ColorEffect_DecreaseBrightness:
+ selectedEffect = compInfo.renderState.colorEffect;
+ break;
+
+ default:
+ break;
}
}
@@ -2164,7 +2152,24 @@ FORCEINLINE void GPUEngineBase::_RenderPixel3D_SSE2(GPUEngineCompositorInfo &com
_mm_unpacklo_epi16(passMask16[1], passMask16[1]),
_mm_unpackhi_epi16(passMask16[1], passMask16[1]) };
- if (_mm_movemask_epi8(enableColorEffectMask) == 0)
+ __m128i dstEffectEnableMask;
+
+#ifdef ENABLE_SSSE3
+ dstEffectEnableMask = _mm_shuffle_epi8(compInfo.renderState.dstBlendEnable_SSSE3, dstLayerID);
+ dstEffectEnableMask = _mm_xor_si128( _mm_cmpeq_epi8(dstEffectEnableMask, _mm_setzero_si128()), _mm_set1_epi32(0xFFFFFFFF) );
+#else
+ dstEffectEnableMask = _mm_and_si128(_mm_cmpeq_epi8(dstLayerID, _mm_set1_epi8(GPULayerID_BG0)), compInfo.renderState.dstBlendEnable_SSE2[GPULayerID_BG0]);
+ dstEffectEnableMask = _mm_or_si128(dstEffectEnableMask, _mm_and_si128(_mm_cmpeq_epi8(dstLayerID, _mm_set1_epi8(GPULayerID_BG1)), compInfo.renderState.dstBlendEnable_SSE2[GPULayerID_BG1]) );
+ dstEffectEnableMask = _mm_or_si128(dstEffectEnableMask, _mm_and_si128(_mm_cmpeq_epi8(dstLayerID, _mm_set1_epi8(GPULayerID_BG2)), compInfo.renderState.dstBlendEnable_SSE2[GPULayerID_BG2]) );
+ dstEffectEnableMask = _mm_or_si128(dstEffectEnableMask, _mm_and_si128(_mm_cmpeq_epi8(dstLayerID, _mm_set1_epi8(GPULayerID_BG3)), compInfo.renderState.dstBlendEnable_SSE2[GPULayerID_BG3]) );
+ dstEffectEnableMask = _mm_or_si128(dstEffectEnableMask, _mm_and_si128(_mm_cmpeq_epi8(dstLayerID, _mm_set1_epi8(GPULayerID_OBJ)), compInfo.renderState.dstBlendEnable_SSE2[GPULayerID_OBJ]) );
+ dstEffectEnableMask = _mm_or_si128(dstEffectEnableMask, _mm_and_si128(_mm_cmpeq_epi8(dstLayerID, _mm_set1_epi8(GPULayerID_Backdrop)), compInfo.renderState.dstBlendEnable_SSE2[GPULayerID_Backdrop]) );
+#endif
+
+ dstEffectEnableMask = _mm_andnot_si128( _mm_cmpeq_epi8(dstLayerID, _mm_set1_epi8(GPULayerID_BG0)), dstEffectEnableMask );
+ const __m128i forceBlendEffectMask = dstEffectEnableMask;
+
+ if (_mm_movemask_epi8( _mm_or_si128(forceBlendEffectMask, enableColorEffectMask) ) == 0)
{
if (OUTPUTFORMAT == NDSColorFormat_BGR555_Rev)
{
@@ -2200,26 +2205,9 @@ FORCEINLINE void GPUEngineBase::_RenderPixel3D_SSE2(GPUEngineCompositorInfo &com
tmpSrc[3] = src3;
}
- const __m128i srcEffectEnableMask = compInfo.renderState.srcBlendEnable_SSE2[GPULayerID_BG0];
- __m128i dstEffectEnableMask;
-
-#ifdef ENABLE_SSSE3
- dstEffectEnableMask = _mm_shuffle_epi8(compInfo.renderState.dstBlendEnable_SSSE3, dstLayerID);
- dstEffectEnableMask = _mm_xor_si128( _mm_cmpeq_epi8(dstEffectEnableMask, _mm_setzero_si128()), _mm_set1_epi32(0xFFFFFFFF) );
-#else
- dstEffectEnableMask = _mm_and_si128(_mm_cmpeq_epi8(dstLayerID, _mm_set1_epi8(GPULayerID_BG0)), compInfo.renderState.dstBlendEnable_SSE2[GPULayerID_BG0]);
- dstEffectEnableMask = _mm_or_si128(dstEffectEnableMask, _mm_and_si128(_mm_cmpeq_epi8(dstLayerID, _mm_set1_epi8(GPULayerID_BG1)), compInfo.renderState.dstBlendEnable_SSE2[GPULayerID_BG1]) );
- dstEffectEnableMask = _mm_or_si128(dstEffectEnableMask, _mm_and_si128(_mm_cmpeq_epi8(dstLayerID, _mm_set1_epi8(GPULayerID_BG2)), compInfo.renderState.dstBlendEnable_SSE2[GPULayerID_BG2]) );
- dstEffectEnableMask = _mm_or_si128(dstEffectEnableMask, _mm_and_si128(_mm_cmpeq_epi8(dstLayerID, _mm_set1_epi8(GPULayerID_BG3)), compInfo.renderState.dstBlendEnable_SSE2[GPULayerID_BG3]) );
- dstEffectEnableMask = _mm_or_si128(dstEffectEnableMask, _mm_and_si128(_mm_cmpeq_epi8(dstLayerID, _mm_set1_epi8(GPULayerID_OBJ)), compInfo.renderState.dstBlendEnable_SSE2[GPULayerID_OBJ]) );
- dstEffectEnableMask = _mm_or_si128(dstEffectEnableMask, _mm_and_si128(_mm_cmpeq_epi8(dstLayerID, _mm_set1_epi8(GPULayerID_Backdrop)), compInfo.renderState.dstBlendEnable_SSE2[GPULayerID_Backdrop]) );
-#endif
-
- dstEffectEnableMask = _mm_andnot_si128( _mm_cmpeq_epi8(dstLayerID, _mm_set1_epi8(GPULayerID_BG0)), dstEffectEnableMask );
-
// Select the color effect based on the BLDCNT target flags.
+ const __m128i srcEffectEnableMask = compInfo.renderState.srcBlendEnable_SSE2[GPULayerID_BG0];
const __m128i colorEffect_vec128 = _mm_blendv_epi8(_mm_set1_epi8(ColorEffect_Disable), _mm_set1_epi8(compInfo.renderState.colorEffect), enableColorEffectMask);
- const __m128i forceBlendEffectMask = _mm_and_si128(enableColorEffectMask, dstEffectEnableMask);
const __m128i evy_vec128 = _mm_set1_epi16(compInfo.renderState.blendEVY);
switch (compInfo.renderState.colorEffect)

0 comments on commit e6b352c

Please sign in to comment.